From 669db206cb1f270046ad400fff7655e20c63e723 Mon Sep 17 00:00:00 2001 From: Gilbert Ramirez Date: Sun, 18 Jul 2004 18:06:47 +0000 Subject: Move dissectors to epan/dissectors directory. Also move ncp222.py, x11-fields, process-x11-fields.pl, make-reg-dotc, and make-reg-dotc.py. Adjust #include lines in files that include packet-*.h files. svn path=/trunk/; revision=11410 --- epan/dissectors/Makefile.am | 117 + epan/dissectors/Makefile.common | 699 + epan/dissectors/Makefile.nmake | 33 + epan/dissectors/make-reg-dotc | 79 + epan/dissectors/make-reg-dotc.py | 118 + epan/dissectors/ncp2222.py | 14808 ++++++++++++++ epan/dissectors/packet-3g-a11.c | 1135 ++ epan/dissectors/packet-aarp.c | 362 + epan/dissectors/packet-acap.c | 193 + epan/dissectors/packet-acse.c | 1767 ++ epan/dissectors/packet-acse.h | 191 + epan/dissectors/packet-afp.c | 4740 +++++ epan/dissectors/packet-afp.h | 122 + epan/dissectors/packet-afs-defs.h | 783 + epan/dissectors/packet-afs-macros.h | 538 + epan/dissectors/packet-afs-register-info.h | 585 + epan/dissectors/packet-afs.c | 1779 ++ epan/dissectors/packet-afs.h | 142 + epan/dissectors/packet-aim-admin.c | 170 + epan/dissectors/packet-aim-adverts.c | 121 + epan/dissectors/packet-aim-bos.c | 175 + epan/dissectors/packet-aim-buddylist.c | 235 + epan/dissectors/packet-aim-chat.c | 193 + epan/dissectors/packet-aim-chatnav.c | 139 + epan/dissectors/packet-aim-directory.c | 124 + epan/dissectors/packet-aim-generic.c | 561 + epan/dissectors/packet-aim-icq.c | 130 + epan/dissectors/packet-aim-invitation.c | 116 + epan/dissectors/packet-aim-location.c | 259 + epan/dissectors/packet-aim-messaging.c | 323 + epan/dissectors/packet-aim-oft.c | 77 + epan/dissectors/packet-aim-popup.c | 125 + epan/dissectors/packet-aim-signon.c | 234 + epan/dissectors/packet-aim-ssi.c | 331 + epan/dissectors/packet-aim-stats.c | 97 + epan/dissectors/packet-aim-translate.c | 99 + epan/dissectors/packet-aim-userlookup.c | 127 + epan/dissectors/packet-aim.c | 1152 ++ epan/dissectors/packet-aim.h | 74 + epan/dissectors/packet-ajp13.c | 877 + epan/dissectors/packet-alcap.c | 1774 ++ epan/dissectors/packet-ans.c | 153 + epan/dissectors/packet-ansi_637.c | 1937 ++ epan/dissectors/packet-ansi_683.c | 2093 ++ epan/dissectors/packet-ansi_801.c | 956 + epan/dissectors/packet-ansi_a.c | 8465 ++++++++ epan/dissectors/packet-ansi_a.h | 57 + epan/dissectors/packet-ansi_map.c | 13242 +++++++++++++ epan/dissectors/packet-ansi_map.h | 41 + epan/dissectors/packet-aodv.c | 979 + epan/dissectors/packet-ap1394.c | 125 + epan/dissectors/packet-ap1394.h | 29 + epan/dissectors/packet-arcnet.c | 389 + epan/dissectors/packet-arcnet.h | 29 + epan/dissectors/packet-arp.c | 1043 + epan/dissectors/packet-arp.h | 35 + epan/dissectors/packet-asap.c | 665 + epan/dissectors/packet-ascend.c | 169 + epan/dissectors/packet-asf.c | 146 + epan/dissectors/packet-atalk.c | 2303 +++ epan/dissectors/packet-atalk.h | 53 + epan/dissectors/packet-atm.c | 1640 ++ epan/dissectors/packet-atm.h | 30 + epan/dissectors/packet-auto_rp.c | 295 + epan/dissectors/packet-bacapp.c | 122 + epan/dissectors/packet-bacnet.c | 595 + epan/dissectors/packet-beep.c | 1121 ++ epan/dissectors/packet-ber.c | 1054 + epan/dissectors/packet-ber.h | 161 + epan/dissectors/packet-bfd.c | 273 + epan/dissectors/packet-bgp.c | 2802 +++ epan/dissectors/packet-bgp.h | 200 + epan/dissectors/packet-bofl.c | 140 + epan/dissectors/packet-bootp.c | 1823 ++ epan/dissectors/packet-bootparams.c | 201 + epan/dissectors/packet-bootparams.h | 13 + epan/dissectors/packet-bpdu.c | 828 + epan/dissectors/packet-brdwlk.c | 404 + epan/dissectors/packet-bssap.c | 480 + epan/dissectors/packet-bssap.h | 34 + epan/dissectors/packet-bssgp.c | 1686 ++ epan/dissectors/packet-bvlc.c | 401 + epan/dissectors/packet-cast.c | 1776 ++ epan/dissectors/packet-ccsds.c | 259 + epan/dissectors/packet-cdp.c | 832 + epan/dissectors/packet-cgmp.c | 143 + epan/dissectors/packet-chdlc.c | 374 + epan/dissectors/packet-chdlc.h | 45 + epan/dissectors/packet-cisco-oui.c | 73 + epan/dissectors/packet-clearcase.c | 79 + epan/dissectors/packet-clearcase.h | 32 + epan/dissectors/packet-clip.c | 120 + epan/dissectors/packet-clip.h | 29 + epan/dissectors/packet-clnp.c | 2396 +++ epan/dissectors/packet-cops.c | 2637 +++ epan/dissectors/packet-cosine.c | 193 + epan/dissectors/packet-cpfi.c | 527 + epan/dissectors/packet-cpha.c | 567 + epan/dissectors/packet-cups.c | 391 + epan/dissectors/packet-data.c | 71 + epan/dissectors/packet-data.h | 29 + epan/dissectors/packet-dccp.c | 564 + epan/dissectors/packet-dccp.h | 415 + epan/dissectors/packet-dcerpc-afs4int.c | 4658 +++++ epan/dissectors/packet-dcerpc-atsvc.c | 682 + epan/dissectors/packet-dcerpc-atsvc.h | 39 + epan/dissectors/packet-dcerpc-bossvr.c | 116 + epan/dissectors/packet-dcerpc-browser.c | 1181 ++ epan/dissectors/packet-dcerpc-browser.h | 42 + epan/dissectors/packet-dcerpc-budb.c | 107 + epan/dissectors/packet-dcerpc-butc.c | 121 + epan/dissectors/packet-dcerpc-cds_clerkserver.c | 111 + epan/dissectors/packet-dcerpc-cds_solicit.c | 83 + epan/dissectors/packet-dcerpc-conv.c | 214 + epan/dissectors/packet-dcerpc-cprpc_server.c | 82 + epan/dissectors/packet-dcerpc-dce122.c | 4428 +++++ epan/dissectors/packet-dcerpc-dce122.h | 32 + epan/dissectors/packet-dcerpc-dcom.h | 82 + epan/dissectors/packet-dcerpc-dfs.c | 102 + epan/dissectors/packet-dcerpc-dfs.h | 55 + epan/dissectors/packet-dcerpc-dnsserver.c | 113 + epan/dissectors/packet-dcerpc-dnsserver.h | 42 + epan/dissectors/packet-dcerpc-drsuapi.c | 122 + epan/dissectors/packet-dcerpc-drsuapi.h | 60 + epan/dissectors/packet-dcerpc-dtsprovider.c | 87 + epan/dissectors/packet-dcerpc-dtsstime_req.c | 82 + epan/dissectors/packet-dcerpc-efs.c | 698 + epan/dissectors/packet-dcerpc-efs.h | 46 + epan/dissectors/packet-dcerpc-epm.c | 735 + epan/dissectors/packet-dcerpc-epm4.c | 735 + epan/dissectors/packet-dcerpc-eventlog.c | 859 + epan/dissectors/packet-dcerpc-eventlog.h | 57 + epan/dissectors/packet-dcerpc-fldb.c | 2142 +++ epan/dissectors/packet-dcerpc-frsapi.c | 106 + epan/dissectors/packet-dcerpc-frsapi.h | 42 + epan/dissectors/packet-dcerpc-frsrpc.c | 114 + epan/dissectors/packet-dcerpc-frsrpc.h | 43 + epan/dissectors/packet-dcerpc-ftserver.c | 104 + epan/dissectors/packet-dcerpc-icl_rpc.c | 86 + epan/dissectors/packet-dcerpc-initshutdown.c | 212 + epan/dissectors/packet-dcerpc-initshutdown.h | 37 + epan/dissectors/packet-dcerpc-krb5rpc.c | 211 + epan/dissectors/packet-dcerpc-llb.c | 90 + epan/dissectors/packet-dcerpc-lsa-ds.c | 378 + epan/dissectors/packet-dcerpc-lsa.c | 4541 +++++ epan/dissectors/packet-dcerpc-lsa.h | 145 + epan/dissectors/packet-dcerpc-mapi.c | 476 + epan/dissectors/packet-dcerpc-mapi.h | 41 + epan/dissectors/packet-dcerpc-messenger.c | 147 + epan/dissectors/packet-dcerpc-mgmt.c | 80 + epan/dissectors/packet-dcerpc-ndr.c | 273 + epan/dissectors/packet-dcerpc-netlogon.c | 7666 ++++++++ epan/dissectors/packet-dcerpc-netlogon.h | 90 + epan/dissectors/packet-dcerpc-nspi.c | 116 + epan/dissectors/packet-dcerpc-nt.c | 1509 ++ epan/dissectors/packet-dcerpc-nt.h | 210 + epan/dissectors/packet-dcerpc-oxid.c | 282 + epan/dissectors/packet-dcerpc-rdaclif.c | 94 + epan/dissectors/packet-dcerpc-reg.c | 926 + epan/dissectors/packet-dcerpc-reg.h | 84 + epan/dissectors/packet-dcerpc-remact.c | 77 + epan/dissectors/packet-dcerpc-rep_proc.c | 93 + epan/dissectors/packet-dcerpc-roverride.c | 88 + epan/dissectors/packet-dcerpc-rpriv.c | 152 + epan/dissectors/packet-dcerpc-rs_acct.c | 168 + epan/dissectors/packet-dcerpc-rs_attr.c | 90 + epan/dissectors/packet-dcerpc-rs_attr_schema.c | 95 + epan/dissectors/packet-dcerpc-rs_bind.c | 89 + epan/dissectors/packet-dcerpc-rs_misc.c | 131 + epan/dissectors/packet-dcerpc-rs_pgo.c | 1900 ++ epan/dissectors/packet-dcerpc-rs_plcy.c | 99 + epan/dissectors/packet-dcerpc-rs_prop_acct.c | 83 + epan/dissectors/packet-dcerpc-rs_prop_acl.c | 88 + epan/dissectors/packet-dcerpc-rs_prop_attr.c | 88 + epan/dissectors/packet-dcerpc-rs_prop_pgo.c | 93 + epan/dissectors/packet-dcerpc-rs_prop_plcy.c | 91 + epan/dissectors/packet-dcerpc-rs_pwd_mgmt.c | 95 + epan/dissectors/packet-dcerpc-rs_repadm.c | 96 + epan/dissectors/packet-dcerpc-rs_replist.c | 92 + epan/dissectors/packet-dcerpc-rs_repmgr.c | 95 + epan/dissectors/packet-dcerpc-rs_unix.c | 82 + epan/dissectors/packet-dcerpc-rsec_login.c | 81 + epan/dissectors/packet-dcerpc-samr.c | 5636 ++++++ epan/dissectors/packet-dcerpc-samr.h | 145 + epan/dissectors/packet-dcerpc-secidmap.c | 88 + epan/dissectors/packet-dcerpc-spoolss.c | 8226 ++++++++ epan/dissectors/packet-dcerpc-spoolss.h | 574 + epan/dissectors/packet-dcerpc-srvsvc.c | 7485 +++++++ epan/dissectors/packet-dcerpc-srvsvc.h | 89 + epan/dissectors/packet-dcerpc-svcctl.c | 618 + epan/dissectors/packet-dcerpc-svcctl.h | 74 + epan/dissectors/packet-dcerpc-tapi.c | 248 + epan/dissectors/packet-dcerpc-tapi.h | 33 + epan/dissectors/packet-dcerpc-tkn4int.c | 92 + epan/dissectors/packet-dcerpc-trksvr.c | 99 + epan/dissectors/packet-dcerpc-ubikdisk.c | 95 + epan/dissectors/packet-dcerpc-ubikvote.c | 90 + epan/dissectors/packet-dcerpc-update.c | 91 + epan/dissectors/packet-dcerpc-wkssvc.c | 1796 ++ epan/dissectors/packet-dcerpc-wkssvc.h | 66 + epan/dissectors/packet-dcerpc.c | 4779 +++++ epan/dissectors/packet-dcerpc.h | 346 + epan/dissectors/packet-dcm.c | 1234 ++ epan/dissectors/packet-ddtp.c | 220 + epan/dissectors/packet-ddtp.h | 56 + epan/dissectors/packet-dec-bpdu.c | 300 + epan/dissectors/packet-dhcpv6.c | 795 + epan/dissectors/packet-diameter-defs.h | 807 + epan/dissectors/packet-diameter.c | 1965 ++ epan/dissectors/packet-diffserv-mpls-common.c | 114 + epan/dissectors/packet-diffserv-mpls-common.h | 52 + epan/dissectors/packet-distcc.c | 440 + epan/dissectors/packet-dlsw.c | 435 + epan/dissectors/packet-dnp.c | 775 + epan/dissectors/packet-dns.c | 2513 +++ epan/dissectors/packet-dns.h | 40 + epan/dissectors/packet-dsi.c | 846 + epan/dissectors/packet-dvmrp.c | 801 + epan/dissectors/packet-dvmrp.h | 31 + epan/dissectors/packet-e164.c | 433 + epan/dissectors/packet-e164.h | 50 + epan/dissectors/packet-eap.c | 1166 ++ epan/dissectors/packet-eapol.c | 431 + epan/dissectors/packet-echo.c | 128 + epan/dissectors/packet-edonkey.c | 1435 ++ epan/dissectors/packet-edonkey.h | 209 + epan/dissectors/packet-eigrp.c | 509 + epan/dissectors/packet-enc.c | 206 + epan/dissectors/packet-enip.c | 2678 +++ epan/dissectors/packet-enrp.c | 904 + epan/dissectors/packet-esis.c | 452 + epan/dissectors/packet-esis.h | 60 + epan/dissectors/packet-eth.c | 471 + epan/dissectors/packet-eth.h | 38 + epan/dissectors/packet-etherip.c | 126 + epan/dissectors/packet-ethertype.c | 300 + epan/dissectors/packet-fc.c | 1454 ++ epan/dissectors/packet-fc.h | 152 + epan/dissectors/packet-fcbls.h | 77 + epan/dissectors/packet-fcct.c | 307 + epan/dissectors/packet-fcct.h | 97 + epan/dissectors/packet-fcdns.c | 1939 ++ epan/dissectors/packet-fcdns.h | 229 + epan/dissectors/packet-fcels.c | 2003 ++ epan/dissectors/packet-fcels.h | 326 + epan/dissectors/packet-fcfcs.c | 1184 ++ epan/dissectors/packet-fcfcs.h | 256 + epan/dissectors/packet-fcfzs.c | 924 + epan/dissectors/packet-fcfzs.h | 121 + epan/dissectors/packet-fcip.c | 680 + epan/dissectors/packet-fclctl.c | 176 + epan/dissectors/packet-fclctl.h | 96 + epan/dissectors/packet-fcp.c | 690 + epan/dissectors/packet-fcp.h | 69 + epan/dissectors/packet-fcsb3.c | 1001 + epan/dissectors/packet-fcsb3.h | 74 + epan/dissectors/packet-fcsp.c | 574 + epan/dissectors/packet-fcsp.h | 57 + epan/dissectors/packet-fcswils.c | 1923 ++ epan/dissectors/packet-fcswils.h | 181 + epan/dissectors/packet-fddi.c | 498 + epan/dissectors/packet-fddi.h | 35 + epan/dissectors/packet-fix.c | 6265 ++++++ epan/dissectors/packet-fr.c | 740 + epan/dissectors/packet-frame.c | 342 + epan/dissectors/packet-frame.h | 49 + epan/dissectors/packet-ftam.c | 3671 ++++ epan/dissectors/packet-ftam.h | 430 + epan/dissectors/packet-ftp.c | 644 + epan/dissectors/packet-fw1.c | 300 + epan/dissectors/packet-gift.c | 160 + epan/dissectors/packet-giop.c | 5654 ++++++ epan/dissectors/packet-giop.h | 603 + epan/dissectors/packet-gmrp.c | 399 + epan/dissectors/packet-gnutella.c | 761 + epan/dissectors/packet-gnutella.h | 80 + epan/dissectors/packet-gprs-llc.c | 388 + epan/dissectors/packet-gprs-ns.c | 366 + epan/dissectors/packet-gre.c | 388 + epan/dissectors/packet-gsm_a.c | 11377 +++++++++++ epan/dissectors/packet-gsm_a.h | 77 + epan/dissectors/packet-gsm_map.c | 3150 +++ epan/dissectors/packet-gsm_map.h | 42 + epan/dissectors/packet-gsm_sms.c | 2628 +++ epan/dissectors/packet-gsm_sms.h | 29 + epan/dissectors/packet-gsm_sms_ud.c | 639 + epan/dissectors/packet-gsm_ss.c | 2490 +++ epan/dissectors/packet-gsm_ss.h | 40 + epan/dissectors/packet-gssapi.c | 479 + epan/dissectors/packet-gssapi.h | 52 + epan/dissectors/packet-gtp.c | 4600 +++++ epan/dissectors/packet-gtp.h | 34 + epan/dissectors/packet-gvrp.c | 349 + epan/dissectors/packet-h1.c | 320 + epan/dissectors/packet-h225.c | 10748 +++++++++++ epan/dissectors/packet-h225.h | 70 + epan/dissectors/packet-h235.c | 1232 ++ epan/dissectors/packet-h235.h | 59 + epan/dissectors/packet-h245.c | 22458 ++++++++++++++++++++++ epan/dissectors/packet-h245.h | 36 + epan/dissectors/packet-h261.c | 263 + epan/dissectors/packet-h263.c | 541 + epan/dissectors/packet-h450.c | 1369 ++ epan/dissectors/packet-hclnfsd.c | 879 + epan/dissectors/packet-hclnfsd.h | 48 + epan/dissectors/packet-hpext.c | 132 + epan/dissectors/packet-hpext.h | 28 + epan/dissectors/packet-hsrp.c | 239 + epan/dissectors/packet-http.c | 1759 ++ epan/dissectors/packet-http.h | 37 + epan/dissectors/packet-hyperscsi.c | 223 + epan/dissectors/packet-iapp.c | 554 + epan/dissectors/packet-iax2.c | 1855 ++ epan/dissectors/packet-iax2.h | 133 + epan/dissectors/packet-ib.c | 239 + epan/dissectors/packet-icap.c | 340 + epan/dissectors/packet-icmpv6.c | 1661 ++ epan/dissectors/packet-icp.c | 254 + epan/dissectors/packet-icq.c | 2222 +++ epan/dissectors/packet-ieee80211.c | 3445 ++++ epan/dissectors/packet-ieee80211.h | 34 + epan/dissectors/packet-ieee8023.c | 121 + epan/dissectors/packet-ieee8023.h | 34 + epan/dissectors/packet-igap.c | 330 + epan/dissectors/packet-igap.h | 35 + epan/dissectors/packet-igmp.c | 1097 ++ epan/dissectors/packet-igmp.h | 32 + epan/dissectors/packet-igrp.c | 249 + epan/dissectors/packet-image-gif.c | 711 + epan/dissectors/packet-image-jfif.c | 1198 ++ epan/dissectors/packet-imap.c | 192 + epan/dissectors/packet-ip.c | 1897 ++ epan/dissectors/packet-ip.h | 48 + epan/dissectors/packet-ipdc.c | 442 + epan/dissectors/packet-ipdc.h | 652 + epan/dissectors/packet-ipfc.c | 140 + epan/dissectors/packet-ipfc.h | 29 + epan/dissectors/packet-ipmi.c | 656 + epan/dissectors/packet-ipp.c | 628 + epan/dissectors/packet-ipsec-udp.c | 107 + epan/dissectors/packet-ipsec.c | 359 + epan/dissectors/packet-ipsec.h | 31 + epan/dissectors/packet-ipv6.c | 960 + epan/dissectors/packet-ipv6.h | 540 + epan/dissectors/packet-ipvs-syncd.c | 353 + epan/dissectors/packet-ipx.c | 1580 ++ epan/dissectors/packet-ipx.h | 178 + epan/dissectors/packet-ipxwan.c | 465 + epan/dissectors/packet-irc.c | 162 + epan/dissectors/packet-isakmp.c | 1720 ++ epan/dissectors/packet-iscsi.c | 2511 +++ epan/dissectors/packet-isdn.c | 216 + epan/dissectors/packet-isis-clv.c | 590 + epan/dissectors/packet-isis-clv.h | 114 + epan/dissectors/packet-isis-hello.c | 928 + epan/dissectors/packet-isis-hello.h | 57 + epan/dissectors/packet-isis-lsp.c | 2008 ++ epan/dissectors/packet-isis-lsp.h | 88 + epan/dissectors/packet-isis-snp.c | 595 + epan/dissectors/packet-isis-snp.h | 40 + epan/dissectors/packet-isis.c | 329 + epan/dissectors/packet-isis.h | 60 + epan/dissectors/packet-isl.c | 341 + epan/dissectors/packet-isl.h | 29 + epan/dissectors/packet-ismp.c | 874 + epan/dissectors/packet-isns.c | 1922 ++ epan/dissectors/packet-isup.c | 6352 ++++++ epan/dissectors/packet-isup.h | 41 + epan/dissectors/packet-iua.c | 909 + epan/dissectors/packet-jabber.c | 143 + epan/dissectors/packet-kadm5.c | 146 + epan/dissectors/packet-kerberos.c | 4173 ++++ epan/dissectors/packet-kerberos.h | 46 + epan/dissectors/packet-klm.c | 267 + epan/dissectors/packet-klm.h | 34 + epan/dissectors/packet-kpasswd.c | 167 + epan/dissectors/packet-l2tp.c | 1082 ++ epan/dissectors/packet-lapb.c | 250 + epan/dissectors/packet-lapbether.c | 109 + epan/dissectors/packet-lapd.c | 296 + epan/dissectors/packet-laplink.c | 261 + epan/dissectors/packet-ldap.c | 3006 +++ epan/dissectors/packet-ldap.h | 90 + epan/dissectors/packet-ldp.c | 3140 +++ epan/dissectors/packet-ldp.h | 34 + epan/dissectors/packet-llc.c | 750 + epan/dissectors/packet-llc.h | 39 + epan/dissectors/packet-lmi.c | 256 + epan/dissectors/packet-lmp.c | 2306 +++ epan/dissectors/packet-lpd.c | 196 + epan/dissectors/packet-lwapp.c | 589 + epan/dissectors/packet-m2pa.c | 465 + epan/dissectors/packet-m2tp.c | 677 + epan/dissectors/packet-m2ua.c | 1160 ++ epan/dissectors/packet-m3ua.c | 2008 ++ epan/dissectors/packet-mbtcp.c | 692 + epan/dissectors/packet-mdshdr.c | 387 + epan/dissectors/packet-media.c | 88 + epan/dissectors/packet-mip.c | 519 + epan/dissectors/packet-mip6.c | 692 + epan/dissectors/packet-mip6.h | 211 + epan/dissectors/packet-mmse.c | 1670 ++ epan/dissectors/packet-mount.c | 1109 ++ epan/dissectors/packet-mount.h | 21 + epan/dissectors/packet-mpeg1.c | 394 + epan/dissectors/packet-mpls-echo.c | 526 + epan/dissectors/packet-mpls.c | 284 + epan/dissectors/packet-mq-pcf.c | 318 + epan/dissectors/packet-mq.c | 3285 ++++ epan/dissectors/packet-mq.h | 36 + epan/dissectors/packet-mrdisc.c | 293 + epan/dissectors/packet-mrdisc.h | 31 + epan/dissectors/packet-msdp.c | 585 + epan/dissectors/packet-msn-messenger.c | 153 + epan/dissectors/packet-msnip.c | 334 + epan/dissectors/packet-msnip.h | 31 + epan/dissectors/packet-msproxy.c | 1291 ++ epan/dissectors/packet-mtp2.c | 219 + epan/dissectors/packet-mtp3.c | 694 + epan/dissectors/packet-mtp3.h | 83 + epan/dissectors/packet-mtp3mg.c | 1244 ++ epan/dissectors/packet-multipart.c | 933 + epan/dissectors/packet-mysql.c | 819 + epan/dissectors/packet-nbipx.c | 802 + epan/dissectors/packet-nbns.c | 1926 ++ epan/dissectors/packet-ncp-int.h | 142 + epan/dissectors/packet-ncp-nmas.c | 734 + epan/dissectors/packet-ncp-nmas.h | 36 + epan/dissectors/packet-ncp.c | 1052 + epan/dissectors/packet-ncp2222.inc | 8650 +++++++++ epan/dissectors/packet-ndmp.c | 3493 ++++ epan/dissectors/packet-ndps.c | 8886 +++++++++ epan/dissectors/packet-ndps.h | 1852 ++ epan/dissectors/packet-netbios.c | 1430 ++ epan/dissectors/packet-netbios.h | 46 + epan/dissectors/packet-netflow.c | 1767 ++ epan/dissectors/packet-nfs.c | 8794 +++++++++ epan/dissectors/packet-nfs.h | 132 + epan/dissectors/packet-nfsacl.c | 638 + epan/dissectors/packet-nfsauth.c | 85 + epan/dissectors/packet-nisplus.c | 1959 ++ epan/dissectors/packet-nisplus.h | 64 + epan/dissectors/packet-nlm.c | 1237 ++ epan/dissectors/packet-nlm.h | 40 + epan/dissectors/packet-nlsp.c | 1659 ++ epan/dissectors/packet-nntp.c | 148 + epan/dissectors/packet-nt-oui.c | 54 + epan/dissectors/packet-nt-sonmp.c | 337 + epan/dissectors/packet-nt-tpcp.c | 257 + epan/dissectors/packet-ntlmssp.c | 1612 ++ epan/dissectors/packet-ntp.c | 954 + epan/dissectors/packet-ntp.h | 38 + epan/dissectors/packet-null.c | 487 + epan/dissectors/packet-null.h | 29 + epan/dissectors/packet-olsr.c | 683 + epan/dissectors/packet-osi-options.c | 460 + epan/dissectors/packet-osi-options.h | 36 + epan/dissectors/packet-osi.c | 305 + epan/dissectors/packet-osi.h | 91 + epan/dissectors/packet-ospf.c | 2145 +++ epan/dissectors/packet-pcnfsd.c | 442 + epan/dissectors/packet-pcnfsd.h | 31 + epan/dissectors/packet-per.c | 1544 ++ epan/dissectors/packet-per.h | 103 + epan/dissectors/packet-pflog.c | 475 + epan/dissectors/packet-pflog.h | 79 + epan/dissectors/packet-pgm.c | 1934 ++ epan/dissectors/packet-pim.c | 1210 ++ epan/dissectors/packet-pim.h | 30 + epan/dissectors/packet-pktc.c | 784 + epan/dissectors/packet-pktc.h | 31 + epan/dissectors/packet-pop.c | 234 + epan/dissectors/packet-portmap.c | 626 + epan/dissectors/packet-portmap.h | 62 + epan/dissectors/packet-postgresql.c | 221 + epan/dissectors/packet-ppp.c | 3767 ++++ epan/dissectors/packet-ppp.h | 44 + epan/dissectors/packet-pppoe.c | 309 + epan/dissectors/packet-pptp.c | 839 + epan/dissectors/packet-pres.c | 1820 ++ epan/dissectors/packet-pres.h | 172 + epan/dissectors/packet-prism.c | 313 + epan/dissectors/packet-prism.h | 37 + epan/dissectors/packet-ptp.c | 2126 ++ epan/dissectors/packet-q2931.c | 2189 +++ epan/dissectors/packet-q931.c | 3166 +++ epan/dissectors/packet-q931.h | 49 + epan/dissectors/packet-q933.c | 2150 +++ epan/dissectors/packet-qllc.c | 196 + epan/dissectors/packet-quake.c | 667 + epan/dissectors/packet-quake2.c | 932 + epan/dissectors/packet-quake3.c | 665 + epan/dissectors/packet-quakeworld.c | 913 + epan/dissectors/packet-radiotap.c | 459 + epan/dissectors/packet-radiotap.h | 30 + epan/dissectors/packet-radius.c | 3427 ++++ epan/dissectors/packet-ranap.c | 4872 +++++ epan/dissectors/packet-raw.c | 204 + epan/dissectors/packet-raw.h | 29 + epan/dissectors/packet-rip.c | 405 + epan/dissectors/packet-ripng.c | 155 + epan/dissectors/packet-ripng.h | 116 + epan/dissectors/packet-rlogin.c | 481 + epan/dissectors/packet-rmcp.c | 191 + epan/dissectors/packet-rmi.c | 384 + epan/dissectors/packet-rmi.h | 69 + epan/dissectors/packet-rmp.c | 270 + epan/dissectors/packet-rpc.c | 3560 ++++ epan/dissectors/packet-rpc.h | 196 + epan/dissectors/packet-rpl.c | 415 + epan/dissectors/packet-rquota.c | 253 + epan/dissectors/packet-rquota.h | 34 + epan/dissectors/packet-rsh.c | 133 + epan/dissectors/packet-rstat.c | 152 + epan/dissectors/packet-rsvp.c | 4609 +++++ epan/dissectors/packet-rsvp.h | 32 + epan/dissectors/packet-rsync.c | 338 + epan/dissectors/packet-rtcp.c | 1655 ++ epan/dissectors/packet-rtcp.h | 44 + epan/dissectors/packet-rtp-events.c | 240 + epan/dissectors/packet-rtp-events.h | 253 + epan/dissectors/packet-rtp.c | 979 + epan/dissectors/packet-rtp.h | 65 + epan/dissectors/packet-rtps.c | 1993 ++ epan/dissectors/packet-rtps.h | 250 + epan/dissectors/packet-rtsp.c | 1217 ++ epan/dissectors/packet-rwall.c | 89 + epan/dissectors/packet-rwall.h | 32 + epan/dissectors/packet-rx.c | 781 + epan/dissectors/packet-rx.h | 82 + epan/dissectors/packet-sadmind.c | 111 + epan/dissectors/packet-sap.c | 362 + epan/dissectors/packet-sccp.c | 2366 +++ epan/dissectors/packet-sccpmg.c | 388 + epan/dissectors/packet-scsi.c | 5337 +++++ epan/dissectors/packet-scsi.h | 83 + epan/dissectors/packet-sctp.c | 2292 +++ epan/dissectors/packet-sctp.h | 43 + epan/dissectors/packet-sdlc.c | 222 + epan/dissectors/packet-sdp.c | 1154 ++ epan/dissectors/packet-sebek.c | 210 + epan/dissectors/packet-ses.c | 1786 ++ epan/dissectors/packet-ses.h | 198 + epan/dissectors/packet-sflow.c | 1068 + epan/dissectors/packet-sigcomp.c | 1975 ++ epan/dissectors/packet-sip.c | 2063 ++ epan/dissectors/packet-sip.h | 39 + epan/dissectors/packet-sipfrag.c | 140 + epan/dissectors/packet-skinny.c | 4402 +++++ epan/dissectors/packet-slimp3.c | 731 + epan/dissectors/packet-sll.c | 307 + epan/dissectors/packet-sll.h | 29 + epan/dissectors/packet-slowprotocols.c | 819 + epan/dissectors/packet-slsk.c | 2480 +++ epan/dissectors/packet-smb-browse.c | 1166 ++ epan/dissectors/packet-smb-browse.h | 34 + epan/dissectors/packet-smb-common.c | 490 + epan/dissectors/packet-smb-common.h | 121 + epan/dissectors/packet-smb-logon.c | 1032 + epan/dissectors/packet-smb-mailslot.c | 265 + epan/dissectors/packet-smb-mailslot.h | 34 + epan/dissectors/packet-smb-pipe.c | 3931 ++++ epan/dissectors/packet-smb-pipe.h | 37 + epan/dissectors/packet-smb-sidsnooping.c | 457 + epan/dissectors/packet-smb-sidsnooping.h | 41 + epan/dissectors/packet-smb.c | 19418 +++++++++++++++++++ epan/dissectors/packet-smpp.c | 2765 +++ epan/dissectors/packet-smtp.c | 597 + epan/dissectors/packet-sna.c | 3597 ++++ epan/dissectors/packet-sna.h | 35 + epan/dissectors/packet-snaeth.c | 113 + epan/dissectors/packet-sndcp.c | 577 + epan/dissectors/packet-snmp.c | 2569 +++ epan/dissectors/packet-snmp.h | 36 + epan/dissectors/packet-socks.c | 1225 ++ epan/dissectors/packet-spnego.c | 1694 ++ epan/dissectors/packet-spray.c | 147 + epan/dissectors/packet-spray.h | 35 + epan/dissectors/packet-srvloc.c | 1699 ++ epan/dissectors/packet-sscop.c | 332 + epan/dissectors/packet-ssh.c | 940 + epan/dissectors/packet-ssl.c | 3468 ++++ epan/dissectors/packet-stat-notify.c | 108 + epan/dissectors/packet-stat-notify.h | 34 + epan/dissectors/packet-stat.c | 351 + epan/dissectors/packet-stat.h | 38 + epan/dissectors/packet-stun.c | 410 + epan/dissectors/packet-sua.c | 1763 ++ epan/dissectors/packet-symantec.c | 103 + epan/dissectors/packet-syslog.c | 253 + epan/dissectors/packet-t38.c | 929 + epan/dissectors/packet-tacacs.c | 1137 ++ epan/dissectors/packet-tacacs.h | 431 + epan/dissectors/packet-tcap.c | 2900 +++ epan/dissectors/packet-tcap.h | 64 + epan/dissectors/packet-tcp.c | 3247 ++++ epan/dissectors/packet-tcp.h | 96 + epan/dissectors/packet-tds.c | 1805 ++ epan/dissectors/packet-teimanagement.c | 146 + epan/dissectors/packet-telnet.c | 1601 ++ epan/dissectors/packet-teredo.c | 267 + epan/dissectors/packet-text-media.c | 164 + epan/dissectors/packet-tftp.c | 352 + epan/dissectors/packet-time.c | 99 + epan/dissectors/packet-tns.c | 1341 ++ epan/dissectors/packet-tns.h | 43 + epan/dissectors/packet-tpkt.c | 395 + epan/dissectors/packet-tpkt.h | 45 + epan/dissectors/packet-tr.c | 749 + epan/dissectors/packet-tr.h | 36 + epan/dissectors/packet-trmac.c | 415 + epan/dissectors/packet-tsp.c | 227 + epan/dissectors/packet-tuxedo.c | 199 + epan/dissectors/packet-tzsp.c | 521 + epan/dissectors/packet-ucp.c | 2595 +++ epan/dissectors/packet-udp.c | 356 + epan/dissectors/packet-udp.h | 42 + epan/dissectors/packet-v120.c | 305 + epan/dissectors/packet-vines.c | 1661 ++ epan/dissectors/packet-vines.h | 135 + epan/dissectors/packet-vj.c | 900 + epan/dissectors/packet-vlan.c | 165 + epan/dissectors/packet-vlan.h | 29 + epan/dissectors/packet-vrrp.c | 302 + epan/dissectors/packet-vtp.c | 698 + epan/dissectors/packet-wap.c | 327 + epan/dissectors/packet-wap.h | 100 + epan/dissectors/packet-wbxml.c | 6731 +++++++ epan/dissectors/packet-wccp.c | 1323 ++ epan/dissectors/packet-wccp.h | 29 + epan/dissectors/packet-wcp.c | 750 + epan/dissectors/packet-wfleet-hdlc.c | 127 + epan/dissectors/packet-who.c | 308 + epan/dissectors/packet-wlancap.c | 302 + epan/dissectors/packet-wlancap.h | 33 + epan/dissectors/packet-wsp.c | 7410 +++++++ epan/dissectors/packet-wsp.h | 60 + epan/dissectors/packet-wtls.c | 1627 ++ epan/dissectors/packet-wtls.h | 40 + epan/dissectors/packet-wtp.c | 1095 ++ epan/dissectors/packet-wtp.h | 63 + epan/dissectors/packet-x11-keysym.h | 349 + epan/dissectors/packet-x11-keysymdef.h | 2063 ++ epan/dissectors/packet-x11.c | 5382 ++++++ epan/dissectors/packet-x25.c | 2518 +++ epan/dissectors/packet-x29.c | 281 + epan/dissectors/packet-xdmcp.c | 520 + epan/dissectors/packet-xot.c | 174 + epan/dissectors/packet-xyplex.c | 215 + epan/dissectors/packet-yhoo.c | 298 + epan/dissectors/packet-ymsg.c | 433 + epan/dissectors/packet-ypbind.c | 222 + epan/dissectors/packet-ypbind.h | 34 + epan/dissectors/packet-yppasswd.c | 173 + epan/dissectors/packet-yppasswd.h | 32 + epan/dissectors/packet-ypserv.c | 494 + epan/dissectors/packet-ypserv.h | 43 + epan/dissectors/packet-ypxfr.c | 81 + epan/dissectors/packet-ypxfr.h | 33 + epan/dissectors/packet-zebra.c | 617 + epan/dissectors/process-x11-fields.pl | 131 + epan/dissectors/x11-fields | 520 + 662 files changed, 618818 insertions(+) create mode 100644 epan/dissectors/Makefile.am create mode 100644 epan/dissectors/Makefile.common create mode 100644 epan/dissectors/Makefile.nmake create mode 100755 epan/dissectors/make-reg-dotc create mode 100755 epan/dissectors/make-reg-dotc.py create mode 100755 epan/dissectors/ncp2222.py create mode 100644 epan/dissectors/packet-3g-a11.c create mode 100644 epan/dissectors/packet-aarp.c create mode 100644 epan/dissectors/packet-acap.c create mode 100644 epan/dissectors/packet-acse.c create mode 100644 epan/dissectors/packet-acse.h create mode 100644 epan/dissectors/packet-afp.c create mode 100644 epan/dissectors/packet-afp.h create mode 100644 epan/dissectors/packet-afs-defs.h create mode 100644 epan/dissectors/packet-afs-macros.h create mode 100644 epan/dissectors/packet-afs-register-info.h create mode 100644 epan/dissectors/packet-afs.c create mode 100644 epan/dissectors/packet-afs.h create mode 100644 epan/dissectors/packet-aim-admin.c create mode 100644 epan/dissectors/packet-aim-adverts.c create mode 100644 epan/dissectors/packet-aim-bos.c create mode 100644 epan/dissectors/packet-aim-buddylist.c create mode 100644 epan/dissectors/packet-aim-chat.c create mode 100644 epan/dissectors/packet-aim-chatnav.c create mode 100644 epan/dissectors/packet-aim-directory.c create mode 100644 epan/dissectors/packet-aim-generic.c create mode 100644 epan/dissectors/packet-aim-icq.c create mode 100644 epan/dissectors/packet-aim-invitation.c create mode 100644 epan/dissectors/packet-aim-location.c create mode 100644 epan/dissectors/packet-aim-messaging.c create mode 100644 epan/dissectors/packet-aim-oft.c create mode 100644 epan/dissectors/packet-aim-popup.c create mode 100644 epan/dissectors/packet-aim-signon.c create mode 100644 epan/dissectors/packet-aim-ssi.c create mode 100644 epan/dissectors/packet-aim-stats.c create mode 100644 epan/dissectors/packet-aim-translate.c create mode 100644 epan/dissectors/packet-aim-userlookup.c create mode 100644 epan/dissectors/packet-aim.c create mode 100644 epan/dissectors/packet-aim.h create mode 100644 epan/dissectors/packet-ajp13.c create mode 100644 epan/dissectors/packet-alcap.c create mode 100644 epan/dissectors/packet-ans.c create mode 100644 epan/dissectors/packet-ansi_637.c create mode 100644 epan/dissectors/packet-ansi_683.c create mode 100644 epan/dissectors/packet-ansi_801.c create mode 100644 epan/dissectors/packet-ansi_a.c create mode 100644 epan/dissectors/packet-ansi_a.h create mode 100644 epan/dissectors/packet-ansi_map.c create mode 100644 epan/dissectors/packet-ansi_map.h create mode 100644 epan/dissectors/packet-aodv.c create mode 100644 epan/dissectors/packet-ap1394.c create mode 100644 epan/dissectors/packet-ap1394.h create mode 100644 epan/dissectors/packet-arcnet.c create mode 100644 epan/dissectors/packet-arcnet.h create mode 100644 epan/dissectors/packet-arp.c create mode 100644 epan/dissectors/packet-arp.h create mode 100644 epan/dissectors/packet-asap.c create mode 100644 epan/dissectors/packet-ascend.c create mode 100644 epan/dissectors/packet-asf.c create mode 100644 epan/dissectors/packet-atalk.c create mode 100644 epan/dissectors/packet-atalk.h create mode 100644 epan/dissectors/packet-atm.c create mode 100644 epan/dissectors/packet-atm.h create mode 100644 epan/dissectors/packet-auto_rp.c create mode 100644 epan/dissectors/packet-bacapp.c create mode 100644 epan/dissectors/packet-bacnet.c create mode 100644 epan/dissectors/packet-beep.c create mode 100644 epan/dissectors/packet-ber.c create mode 100644 epan/dissectors/packet-ber.h create mode 100644 epan/dissectors/packet-bfd.c create mode 100644 epan/dissectors/packet-bgp.c create mode 100644 epan/dissectors/packet-bgp.h create mode 100644 epan/dissectors/packet-bofl.c create mode 100644 epan/dissectors/packet-bootp.c create mode 100644 epan/dissectors/packet-bootparams.c create mode 100644 epan/dissectors/packet-bootparams.h create mode 100644 epan/dissectors/packet-bpdu.c create mode 100644 epan/dissectors/packet-brdwlk.c create mode 100644 epan/dissectors/packet-bssap.c create mode 100644 epan/dissectors/packet-bssap.h create mode 100644 epan/dissectors/packet-bssgp.c create mode 100644 epan/dissectors/packet-bvlc.c create mode 100644 epan/dissectors/packet-cast.c create mode 100644 epan/dissectors/packet-ccsds.c create mode 100644 epan/dissectors/packet-cdp.c create mode 100644 epan/dissectors/packet-cgmp.c create mode 100644 epan/dissectors/packet-chdlc.c create mode 100644 epan/dissectors/packet-chdlc.h create mode 100644 epan/dissectors/packet-cisco-oui.c create mode 100644 epan/dissectors/packet-clearcase.c create mode 100644 epan/dissectors/packet-clearcase.h create mode 100644 epan/dissectors/packet-clip.c create mode 100644 epan/dissectors/packet-clip.h create mode 100644 epan/dissectors/packet-clnp.c create mode 100644 epan/dissectors/packet-cops.c create mode 100644 epan/dissectors/packet-cosine.c create mode 100644 epan/dissectors/packet-cpfi.c create mode 100644 epan/dissectors/packet-cpha.c create mode 100644 epan/dissectors/packet-cups.c create mode 100644 epan/dissectors/packet-data.c create mode 100644 epan/dissectors/packet-data.h create mode 100644 epan/dissectors/packet-dccp.c create mode 100644 epan/dissectors/packet-dccp.h create mode 100644 epan/dissectors/packet-dcerpc-afs4int.c create mode 100644 epan/dissectors/packet-dcerpc-atsvc.c create mode 100644 epan/dissectors/packet-dcerpc-atsvc.h create mode 100644 epan/dissectors/packet-dcerpc-bossvr.c create mode 100644 epan/dissectors/packet-dcerpc-browser.c create mode 100644 epan/dissectors/packet-dcerpc-browser.h create mode 100644 epan/dissectors/packet-dcerpc-budb.c create mode 100644 epan/dissectors/packet-dcerpc-butc.c create mode 100644 epan/dissectors/packet-dcerpc-cds_clerkserver.c create mode 100644 epan/dissectors/packet-dcerpc-cds_solicit.c create mode 100644 epan/dissectors/packet-dcerpc-conv.c create mode 100644 epan/dissectors/packet-dcerpc-cprpc_server.c create mode 100644 epan/dissectors/packet-dcerpc-dce122.c create mode 100644 epan/dissectors/packet-dcerpc-dce122.h create mode 100644 epan/dissectors/packet-dcerpc-dcom.h create mode 100644 epan/dissectors/packet-dcerpc-dfs.c create mode 100644 epan/dissectors/packet-dcerpc-dfs.h create mode 100644 epan/dissectors/packet-dcerpc-dnsserver.c create mode 100644 epan/dissectors/packet-dcerpc-dnsserver.h create mode 100644 epan/dissectors/packet-dcerpc-drsuapi.c create mode 100644 epan/dissectors/packet-dcerpc-drsuapi.h create mode 100644 epan/dissectors/packet-dcerpc-dtsprovider.c create mode 100644 epan/dissectors/packet-dcerpc-dtsstime_req.c create mode 100644 epan/dissectors/packet-dcerpc-efs.c create mode 100644 epan/dissectors/packet-dcerpc-efs.h create mode 100644 epan/dissectors/packet-dcerpc-epm.c create mode 100644 epan/dissectors/packet-dcerpc-epm4.c create mode 100644 epan/dissectors/packet-dcerpc-eventlog.c create mode 100644 epan/dissectors/packet-dcerpc-eventlog.h create mode 100644 epan/dissectors/packet-dcerpc-fldb.c create mode 100644 epan/dissectors/packet-dcerpc-frsapi.c create mode 100644 epan/dissectors/packet-dcerpc-frsapi.h create mode 100644 epan/dissectors/packet-dcerpc-frsrpc.c create mode 100644 epan/dissectors/packet-dcerpc-frsrpc.h create mode 100644 epan/dissectors/packet-dcerpc-ftserver.c create mode 100644 epan/dissectors/packet-dcerpc-icl_rpc.c create mode 100644 epan/dissectors/packet-dcerpc-initshutdown.c create mode 100644 epan/dissectors/packet-dcerpc-initshutdown.h create mode 100644 epan/dissectors/packet-dcerpc-krb5rpc.c create mode 100644 epan/dissectors/packet-dcerpc-llb.c create mode 100644 epan/dissectors/packet-dcerpc-lsa-ds.c create mode 100644 epan/dissectors/packet-dcerpc-lsa.c create mode 100644 epan/dissectors/packet-dcerpc-lsa.h create mode 100644 epan/dissectors/packet-dcerpc-mapi.c create mode 100644 epan/dissectors/packet-dcerpc-mapi.h create mode 100644 epan/dissectors/packet-dcerpc-messenger.c create mode 100644 epan/dissectors/packet-dcerpc-mgmt.c create mode 100644 epan/dissectors/packet-dcerpc-ndr.c create mode 100644 epan/dissectors/packet-dcerpc-netlogon.c create mode 100644 epan/dissectors/packet-dcerpc-netlogon.h create mode 100644 epan/dissectors/packet-dcerpc-nspi.c create mode 100644 epan/dissectors/packet-dcerpc-nt.c create mode 100644 epan/dissectors/packet-dcerpc-nt.h create mode 100644 epan/dissectors/packet-dcerpc-oxid.c create mode 100644 epan/dissectors/packet-dcerpc-rdaclif.c create mode 100644 epan/dissectors/packet-dcerpc-reg.c create mode 100644 epan/dissectors/packet-dcerpc-reg.h create mode 100644 epan/dissectors/packet-dcerpc-remact.c create mode 100644 epan/dissectors/packet-dcerpc-rep_proc.c create mode 100644 epan/dissectors/packet-dcerpc-roverride.c create mode 100644 epan/dissectors/packet-dcerpc-rpriv.c create mode 100644 epan/dissectors/packet-dcerpc-rs_acct.c create mode 100644 epan/dissectors/packet-dcerpc-rs_attr.c create mode 100644 epan/dissectors/packet-dcerpc-rs_attr_schema.c create mode 100644 epan/dissectors/packet-dcerpc-rs_bind.c create mode 100644 epan/dissectors/packet-dcerpc-rs_misc.c create mode 100644 epan/dissectors/packet-dcerpc-rs_pgo.c create mode 100644 epan/dissectors/packet-dcerpc-rs_plcy.c create mode 100644 epan/dissectors/packet-dcerpc-rs_prop_acct.c create mode 100644 epan/dissectors/packet-dcerpc-rs_prop_acl.c create mode 100644 epan/dissectors/packet-dcerpc-rs_prop_attr.c create mode 100644 epan/dissectors/packet-dcerpc-rs_prop_pgo.c create mode 100644 epan/dissectors/packet-dcerpc-rs_prop_plcy.c create mode 100644 epan/dissectors/packet-dcerpc-rs_pwd_mgmt.c create mode 100644 epan/dissectors/packet-dcerpc-rs_repadm.c create mode 100644 epan/dissectors/packet-dcerpc-rs_replist.c create mode 100644 epan/dissectors/packet-dcerpc-rs_repmgr.c create mode 100644 epan/dissectors/packet-dcerpc-rs_unix.c create mode 100644 epan/dissectors/packet-dcerpc-rsec_login.c create mode 100644 epan/dissectors/packet-dcerpc-samr.c create mode 100644 epan/dissectors/packet-dcerpc-samr.h create mode 100644 epan/dissectors/packet-dcerpc-secidmap.c create mode 100644 epan/dissectors/packet-dcerpc-spoolss.c create mode 100644 epan/dissectors/packet-dcerpc-spoolss.h create mode 100644 epan/dissectors/packet-dcerpc-srvsvc.c create mode 100644 epan/dissectors/packet-dcerpc-srvsvc.h create mode 100644 epan/dissectors/packet-dcerpc-svcctl.c create mode 100644 epan/dissectors/packet-dcerpc-svcctl.h create mode 100644 epan/dissectors/packet-dcerpc-tapi.c create mode 100644 epan/dissectors/packet-dcerpc-tapi.h create mode 100644 epan/dissectors/packet-dcerpc-tkn4int.c create mode 100644 epan/dissectors/packet-dcerpc-trksvr.c create mode 100644 epan/dissectors/packet-dcerpc-ubikdisk.c create mode 100644 epan/dissectors/packet-dcerpc-ubikvote.c create mode 100644 epan/dissectors/packet-dcerpc-update.c create mode 100644 epan/dissectors/packet-dcerpc-wkssvc.c create mode 100644 epan/dissectors/packet-dcerpc-wkssvc.h create mode 100644 epan/dissectors/packet-dcerpc.c create mode 100644 epan/dissectors/packet-dcerpc.h create mode 100644 epan/dissectors/packet-dcm.c create mode 100644 epan/dissectors/packet-ddtp.c create mode 100644 epan/dissectors/packet-ddtp.h create mode 100644 epan/dissectors/packet-dec-bpdu.c create mode 100644 epan/dissectors/packet-dhcpv6.c create mode 100644 epan/dissectors/packet-diameter-defs.h create mode 100644 epan/dissectors/packet-diameter.c create mode 100644 epan/dissectors/packet-diffserv-mpls-common.c create mode 100644 epan/dissectors/packet-diffserv-mpls-common.h create mode 100644 epan/dissectors/packet-distcc.c create mode 100644 epan/dissectors/packet-dlsw.c create mode 100644 epan/dissectors/packet-dnp.c create mode 100644 epan/dissectors/packet-dns.c create mode 100644 epan/dissectors/packet-dns.h create mode 100644 epan/dissectors/packet-dsi.c create mode 100644 epan/dissectors/packet-dvmrp.c create mode 100644 epan/dissectors/packet-dvmrp.h create mode 100644 epan/dissectors/packet-e164.c create mode 100644 epan/dissectors/packet-e164.h create mode 100644 epan/dissectors/packet-eap.c create mode 100644 epan/dissectors/packet-eapol.c create mode 100644 epan/dissectors/packet-echo.c create mode 100644 epan/dissectors/packet-edonkey.c create mode 100644 epan/dissectors/packet-edonkey.h create mode 100644 epan/dissectors/packet-eigrp.c create mode 100644 epan/dissectors/packet-enc.c create mode 100644 epan/dissectors/packet-enip.c create mode 100644 epan/dissectors/packet-enrp.c create mode 100644 epan/dissectors/packet-esis.c create mode 100644 epan/dissectors/packet-esis.h create mode 100644 epan/dissectors/packet-eth.c create mode 100644 epan/dissectors/packet-eth.h create mode 100644 epan/dissectors/packet-etherip.c create mode 100644 epan/dissectors/packet-ethertype.c create mode 100644 epan/dissectors/packet-fc.c create mode 100644 epan/dissectors/packet-fc.h create mode 100644 epan/dissectors/packet-fcbls.h create mode 100644 epan/dissectors/packet-fcct.c create mode 100644 epan/dissectors/packet-fcct.h create mode 100644 epan/dissectors/packet-fcdns.c create mode 100644 epan/dissectors/packet-fcdns.h create mode 100644 epan/dissectors/packet-fcels.c create mode 100644 epan/dissectors/packet-fcels.h create mode 100644 epan/dissectors/packet-fcfcs.c create mode 100644 epan/dissectors/packet-fcfcs.h create mode 100644 epan/dissectors/packet-fcfzs.c create mode 100644 epan/dissectors/packet-fcfzs.h create mode 100644 epan/dissectors/packet-fcip.c create mode 100644 epan/dissectors/packet-fclctl.c create mode 100644 epan/dissectors/packet-fclctl.h create mode 100644 epan/dissectors/packet-fcp.c create mode 100644 epan/dissectors/packet-fcp.h create mode 100644 epan/dissectors/packet-fcsb3.c create mode 100644 epan/dissectors/packet-fcsb3.h create mode 100644 epan/dissectors/packet-fcsp.c create mode 100644 epan/dissectors/packet-fcsp.h create mode 100644 epan/dissectors/packet-fcswils.c create mode 100644 epan/dissectors/packet-fcswils.h create mode 100644 epan/dissectors/packet-fddi.c create mode 100644 epan/dissectors/packet-fddi.h create mode 100644 epan/dissectors/packet-fix.c create mode 100644 epan/dissectors/packet-fr.c create mode 100644 epan/dissectors/packet-frame.c create mode 100644 epan/dissectors/packet-frame.h create mode 100644 epan/dissectors/packet-ftam.c create mode 100644 epan/dissectors/packet-ftam.h create mode 100644 epan/dissectors/packet-ftp.c create mode 100644 epan/dissectors/packet-fw1.c create mode 100644 epan/dissectors/packet-gift.c create mode 100644 epan/dissectors/packet-giop.c create mode 100644 epan/dissectors/packet-giop.h create mode 100644 epan/dissectors/packet-gmrp.c create mode 100644 epan/dissectors/packet-gnutella.c create mode 100644 epan/dissectors/packet-gnutella.h create mode 100644 epan/dissectors/packet-gprs-llc.c create mode 100644 epan/dissectors/packet-gprs-ns.c create mode 100644 epan/dissectors/packet-gre.c create mode 100644 epan/dissectors/packet-gsm_a.c create mode 100644 epan/dissectors/packet-gsm_a.h create mode 100644 epan/dissectors/packet-gsm_map.c create mode 100644 epan/dissectors/packet-gsm_map.h create mode 100644 epan/dissectors/packet-gsm_sms.c create mode 100644 epan/dissectors/packet-gsm_sms.h create mode 100644 epan/dissectors/packet-gsm_sms_ud.c create mode 100644 epan/dissectors/packet-gsm_ss.c create mode 100644 epan/dissectors/packet-gsm_ss.h create mode 100644 epan/dissectors/packet-gssapi.c create mode 100644 epan/dissectors/packet-gssapi.h create mode 100644 epan/dissectors/packet-gtp.c create mode 100644 epan/dissectors/packet-gtp.h create mode 100644 epan/dissectors/packet-gvrp.c create mode 100644 epan/dissectors/packet-h1.c create mode 100644 epan/dissectors/packet-h225.c create mode 100644 epan/dissectors/packet-h225.h create mode 100644 epan/dissectors/packet-h235.c create mode 100644 epan/dissectors/packet-h235.h create mode 100644 epan/dissectors/packet-h245.c create mode 100644 epan/dissectors/packet-h245.h create mode 100644 epan/dissectors/packet-h261.c create mode 100644 epan/dissectors/packet-h263.c create mode 100644 epan/dissectors/packet-h450.c create mode 100644 epan/dissectors/packet-hclnfsd.c create mode 100644 epan/dissectors/packet-hclnfsd.h create mode 100644 epan/dissectors/packet-hpext.c create mode 100644 epan/dissectors/packet-hpext.h create mode 100644 epan/dissectors/packet-hsrp.c create mode 100644 epan/dissectors/packet-http.c create mode 100644 epan/dissectors/packet-http.h create mode 100644 epan/dissectors/packet-hyperscsi.c create mode 100644 epan/dissectors/packet-iapp.c create mode 100644 epan/dissectors/packet-iax2.c create mode 100644 epan/dissectors/packet-iax2.h create mode 100644 epan/dissectors/packet-ib.c create mode 100644 epan/dissectors/packet-icap.c create mode 100644 epan/dissectors/packet-icmpv6.c create mode 100644 epan/dissectors/packet-icp.c create mode 100644 epan/dissectors/packet-icq.c create mode 100644 epan/dissectors/packet-ieee80211.c create mode 100644 epan/dissectors/packet-ieee80211.h create mode 100644 epan/dissectors/packet-ieee8023.c create mode 100644 epan/dissectors/packet-ieee8023.h create mode 100644 epan/dissectors/packet-igap.c create mode 100644 epan/dissectors/packet-igap.h create mode 100644 epan/dissectors/packet-igmp.c create mode 100644 epan/dissectors/packet-igmp.h create mode 100644 epan/dissectors/packet-igrp.c create mode 100644 epan/dissectors/packet-image-gif.c create mode 100644 epan/dissectors/packet-image-jfif.c create mode 100644 epan/dissectors/packet-imap.c create mode 100644 epan/dissectors/packet-ip.c create mode 100644 epan/dissectors/packet-ip.h create mode 100644 epan/dissectors/packet-ipdc.c create mode 100644 epan/dissectors/packet-ipdc.h create mode 100644 epan/dissectors/packet-ipfc.c create mode 100644 epan/dissectors/packet-ipfc.h create mode 100644 epan/dissectors/packet-ipmi.c create mode 100644 epan/dissectors/packet-ipp.c create mode 100644 epan/dissectors/packet-ipsec-udp.c create mode 100644 epan/dissectors/packet-ipsec.c create mode 100644 epan/dissectors/packet-ipsec.h create mode 100644 epan/dissectors/packet-ipv6.c create mode 100644 epan/dissectors/packet-ipv6.h create mode 100644 epan/dissectors/packet-ipvs-syncd.c create mode 100644 epan/dissectors/packet-ipx.c create mode 100644 epan/dissectors/packet-ipx.h create mode 100644 epan/dissectors/packet-ipxwan.c create mode 100644 epan/dissectors/packet-irc.c create mode 100644 epan/dissectors/packet-isakmp.c create mode 100644 epan/dissectors/packet-iscsi.c create mode 100644 epan/dissectors/packet-isdn.c create mode 100644 epan/dissectors/packet-isis-clv.c create mode 100644 epan/dissectors/packet-isis-clv.h create mode 100644 epan/dissectors/packet-isis-hello.c create mode 100644 epan/dissectors/packet-isis-hello.h create mode 100644 epan/dissectors/packet-isis-lsp.c create mode 100644 epan/dissectors/packet-isis-lsp.h create mode 100644 epan/dissectors/packet-isis-snp.c create mode 100644 epan/dissectors/packet-isis-snp.h create mode 100644 epan/dissectors/packet-isis.c create mode 100644 epan/dissectors/packet-isis.h create mode 100644 epan/dissectors/packet-isl.c create mode 100644 epan/dissectors/packet-isl.h create mode 100644 epan/dissectors/packet-ismp.c create mode 100644 epan/dissectors/packet-isns.c create mode 100644 epan/dissectors/packet-isup.c create mode 100644 epan/dissectors/packet-isup.h create mode 100644 epan/dissectors/packet-iua.c create mode 100644 epan/dissectors/packet-jabber.c create mode 100644 epan/dissectors/packet-kadm5.c create mode 100644 epan/dissectors/packet-kerberos.c create mode 100644 epan/dissectors/packet-kerberos.h create mode 100644 epan/dissectors/packet-klm.c create mode 100644 epan/dissectors/packet-klm.h create mode 100644 epan/dissectors/packet-kpasswd.c create mode 100644 epan/dissectors/packet-l2tp.c create mode 100644 epan/dissectors/packet-lapb.c create mode 100644 epan/dissectors/packet-lapbether.c create mode 100644 epan/dissectors/packet-lapd.c create mode 100644 epan/dissectors/packet-laplink.c create mode 100644 epan/dissectors/packet-ldap.c create mode 100644 epan/dissectors/packet-ldap.h create mode 100644 epan/dissectors/packet-ldp.c create mode 100644 epan/dissectors/packet-ldp.h create mode 100644 epan/dissectors/packet-llc.c create mode 100644 epan/dissectors/packet-llc.h create mode 100644 epan/dissectors/packet-lmi.c create mode 100644 epan/dissectors/packet-lmp.c create mode 100644 epan/dissectors/packet-lpd.c create mode 100644 epan/dissectors/packet-lwapp.c create mode 100644 epan/dissectors/packet-m2pa.c create mode 100644 epan/dissectors/packet-m2tp.c create mode 100644 epan/dissectors/packet-m2ua.c create mode 100644 epan/dissectors/packet-m3ua.c create mode 100644 epan/dissectors/packet-mbtcp.c create mode 100644 epan/dissectors/packet-mdshdr.c create mode 100644 epan/dissectors/packet-media.c create mode 100644 epan/dissectors/packet-mip.c create mode 100644 epan/dissectors/packet-mip6.c create mode 100644 epan/dissectors/packet-mip6.h create mode 100644 epan/dissectors/packet-mmse.c create mode 100644 epan/dissectors/packet-mount.c create mode 100644 epan/dissectors/packet-mount.h create mode 100644 epan/dissectors/packet-mpeg1.c create mode 100644 epan/dissectors/packet-mpls-echo.c create mode 100644 epan/dissectors/packet-mpls.c create mode 100644 epan/dissectors/packet-mq-pcf.c create mode 100644 epan/dissectors/packet-mq.c create mode 100644 epan/dissectors/packet-mq.h create mode 100644 epan/dissectors/packet-mrdisc.c create mode 100644 epan/dissectors/packet-mrdisc.h create mode 100644 epan/dissectors/packet-msdp.c create mode 100644 epan/dissectors/packet-msn-messenger.c create mode 100644 epan/dissectors/packet-msnip.c create mode 100644 epan/dissectors/packet-msnip.h create mode 100644 epan/dissectors/packet-msproxy.c create mode 100644 epan/dissectors/packet-mtp2.c create mode 100644 epan/dissectors/packet-mtp3.c create mode 100644 epan/dissectors/packet-mtp3.h create mode 100644 epan/dissectors/packet-mtp3mg.c create mode 100644 epan/dissectors/packet-multipart.c create mode 100644 epan/dissectors/packet-mysql.c create mode 100644 epan/dissectors/packet-nbipx.c create mode 100644 epan/dissectors/packet-nbns.c create mode 100644 epan/dissectors/packet-ncp-int.h create mode 100644 epan/dissectors/packet-ncp-nmas.c create mode 100644 epan/dissectors/packet-ncp-nmas.h create mode 100644 epan/dissectors/packet-ncp.c create mode 100644 epan/dissectors/packet-ncp2222.inc create mode 100644 epan/dissectors/packet-ndmp.c create mode 100644 epan/dissectors/packet-ndps.c create mode 100644 epan/dissectors/packet-ndps.h create mode 100644 epan/dissectors/packet-netbios.c create mode 100644 epan/dissectors/packet-netbios.h create mode 100644 epan/dissectors/packet-netflow.c create mode 100644 epan/dissectors/packet-nfs.c create mode 100644 epan/dissectors/packet-nfs.h create mode 100644 epan/dissectors/packet-nfsacl.c create mode 100644 epan/dissectors/packet-nfsauth.c create mode 100644 epan/dissectors/packet-nisplus.c create mode 100644 epan/dissectors/packet-nisplus.h create mode 100644 epan/dissectors/packet-nlm.c create mode 100644 epan/dissectors/packet-nlm.h create mode 100644 epan/dissectors/packet-nlsp.c create mode 100644 epan/dissectors/packet-nntp.c create mode 100644 epan/dissectors/packet-nt-oui.c create mode 100644 epan/dissectors/packet-nt-sonmp.c create mode 100644 epan/dissectors/packet-nt-tpcp.c create mode 100644 epan/dissectors/packet-ntlmssp.c create mode 100644 epan/dissectors/packet-ntp.c create mode 100644 epan/dissectors/packet-ntp.h create mode 100644 epan/dissectors/packet-null.c create mode 100644 epan/dissectors/packet-null.h create mode 100644 epan/dissectors/packet-olsr.c create mode 100644 epan/dissectors/packet-osi-options.c create mode 100644 epan/dissectors/packet-osi-options.h create mode 100644 epan/dissectors/packet-osi.c create mode 100644 epan/dissectors/packet-osi.h create mode 100644 epan/dissectors/packet-ospf.c create mode 100644 epan/dissectors/packet-pcnfsd.c create mode 100644 epan/dissectors/packet-pcnfsd.h create mode 100644 epan/dissectors/packet-per.c create mode 100644 epan/dissectors/packet-per.h create mode 100644 epan/dissectors/packet-pflog.c create mode 100644 epan/dissectors/packet-pflog.h create mode 100644 epan/dissectors/packet-pgm.c create mode 100644 epan/dissectors/packet-pim.c create mode 100644 epan/dissectors/packet-pim.h create mode 100644 epan/dissectors/packet-pktc.c create mode 100644 epan/dissectors/packet-pktc.h create mode 100644 epan/dissectors/packet-pop.c create mode 100644 epan/dissectors/packet-portmap.c create mode 100644 epan/dissectors/packet-portmap.h create mode 100644 epan/dissectors/packet-postgresql.c create mode 100644 epan/dissectors/packet-ppp.c create mode 100644 epan/dissectors/packet-ppp.h create mode 100644 epan/dissectors/packet-pppoe.c create mode 100644 epan/dissectors/packet-pptp.c create mode 100644 epan/dissectors/packet-pres.c create mode 100644 epan/dissectors/packet-pres.h create mode 100644 epan/dissectors/packet-prism.c create mode 100644 epan/dissectors/packet-prism.h create mode 100644 epan/dissectors/packet-ptp.c create mode 100644 epan/dissectors/packet-q2931.c create mode 100644 epan/dissectors/packet-q931.c create mode 100644 epan/dissectors/packet-q931.h create mode 100644 epan/dissectors/packet-q933.c create mode 100644 epan/dissectors/packet-qllc.c create mode 100644 epan/dissectors/packet-quake.c create mode 100644 epan/dissectors/packet-quake2.c create mode 100644 epan/dissectors/packet-quake3.c create mode 100644 epan/dissectors/packet-quakeworld.c create mode 100644 epan/dissectors/packet-radiotap.c create mode 100644 epan/dissectors/packet-radiotap.h create mode 100644 epan/dissectors/packet-radius.c create mode 100644 epan/dissectors/packet-ranap.c create mode 100644 epan/dissectors/packet-raw.c create mode 100644 epan/dissectors/packet-raw.h create mode 100644 epan/dissectors/packet-rip.c create mode 100644 epan/dissectors/packet-ripng.c create mode 100644 epan/dissectors/packet-ripng.h create mode 100644 epan/dissectors/packet-rlogin.c create mode 100644 epan/dissectors/packet-rmcp.c create mode 100644 epan/dissectors/packet-rmi.c create mode 100644 epan/dissectors/packet-rmi.h create mode 100644 epan/dissectors/packet-rmp.c create mode 100644 epan/dissectors/packet-rpc.c create mode 100644 epan/dissectors/packet-rpc.h create mode 100644 epan/dissectors/packet-rpl.c create mode 100644 epan/dissectors/packet-rquota.c create mode 100644 epan/dissectors/packet-rquota.h create mode 100644 epan/dissectors/packet-rsh.c create mode 100644 epan/dissectors/packet-rstat.c create mode 100644 epan/dissectors/packet-rsvp.c create mode 100644 epan/dissectors/packet-rsvp.h create mode 100644 epan/dissectors/packet-rsync.c create mode 100644 epan/dissectors/packet-rtcp.c create mode 100644 epan/dissectors/packet-rtcp.h create mode 100644 epan/dissectors/packet-rtp-events.c create mode 100644 epan/dissectors/packet-rtp-events.h create mode 100644 epan/dissectors/packet-rtp.c create mode 100644 epan/dissectors/packet-rtp.h create mode 100644 epan/dissectors/packet-rtps.c create mode 100644 epan/dissectors/packet-rtps.h create mode 100644 epan/dissectors/packet-rtsp.c create mode 100644 epan/dissectors/packet-rwall.c create mode 100644 epan/dissectors/packet-rwall.h create mode 100644 epan/dissectors/packet-rx.c create mode 100644 epan/dissectors/packet-rx.h create mode 100644 epan/dissectors/packet-sadmind.c create mode 100644 epan/dissectors/packet-sap.c create mode 100644 epan/dissectors/packet-sccp.c create mode 100644 epan/dissectors/packet-sccpmg.c create mode 100644 epan/dissectors/packet-scsi.c create mode 100644 epan/dissectors/packet-scsi.h create mode 100644 epan/dissectors/packet-sctp.c create mode 100644 epan/dissectors/packet-sctp.h create mode 100644 epan/dissectors/packet-sdlc.c create mode 100644 epan/dissectors/packet-sdp.c create mode 100644 epan/dissectors/packet-sebek.c create mode 100644 epan/dissectors/packet-ses.c create mode 100644 epan/dissectors/packet-ses.h create mode 100644 epan/dissectors/packet-sflow.c create mode 100644 epan/dissectors/packet-sigcomp.c create mode 100644 epan/dissectors/packet-sip.c create mode 100644 epan/dissectors/packet-sip.h create mode 100644 epan/dissectors/packet-sipfrag.c create mode 100644 epan/dissectors/packet-skinny.c create mode 100644 epan/dissectors/packet-slimp3.c create mode 100644 epan/dissectors/packet-sll.c create mode 100644 epan/dissectors/packet-sll.h create mode 100644 epan/dissectors/packet-slowprotocols.c create mode 100644 epan/dissectors/packet-slsk.c create mode 100644 epan/dissectors/packet-smb-browse.c create mode 100644 epan/dissectors/packet-smb-browse.h create mode 100644 epan/dissectors/packet-smb-common.c create mode 100644 epan/dissectors/packet-smb-common.h create mode 100644 epan/dissectors/packet-smb-logon.c create mode 100644 epan/dissectors/packet-smb-mailslot.c create mode 100644 epan/dissectors/packet-smb-mailslot.h create mode 100644 epan/dissectors/packet-smb-pipe.c create mode 100644 epan/dissectors/packet-smb-pipe.h create mode 100644 epan/dissectors/packet-smb-sidsnooping.c create mode 100644 epan/dissectors/packet-smb-sidsnooping.h create mode 100644 epan/dissectors/packet-smb.c create mode 100644 epan/dissectors/packet-smpp.c create mode 100644 epan/dissectors/packet-smtp.c create mode 100644 epan/dissectors/packet-sna.c create mode 100644 epan/dissectors/packet-sna.h create mode 100644 epan/dissectors/packet-snaeth.c create mode 100644 epan/dissectors/packet-sndcp.c create mode 100644 epan/dissectors/packet-snmp.c create mode 100644 epan/dissectors/packet-snmp.h create mode 100644 epan/dissectors/packet-socks.c create mode 100644 epan/dissectors/packet-spnego.c create mode 100644 epan/dissectors/packet-spray.c create mode 100644 epan/dissectors/packet-spray.h create mode 100644 epan/dissectors/packet-srvloc.c create mode 100644 epan/dissectors/packet-sscop.c create mode 100644 epan/dissectors/packet-ssh.c create mode 100644 epan/dissectors/packet-ssl.c create mode 100644 epan/dissectors/packet-stat-notify.c create mode 100644 epan/dissectors/packet-stat-notify.h create mode 100644 epan/dissectors/packet-stat.c create mode 100644 epan/dissectors/packet-stat.h create mode 100644 epan/dissectors/packet-stun.c create mode 100644 epan/dissectors/packet-sua.c create mode 100644 epan/dissectors/packet-symantec.c create mode 100644 epan/dissectors/packet-syslog.c create mode 100644 epan/dissectors/packet-t38.c create mode 100644 epan/dissectors/packet-tacacs.c create mode 100644 epan/dissectors/packet-tacacs.h create mode 100644 epan/dissectors/packet-tcap.c create mode 100644 epan/dissectors/packet-tcap.h create mode 100644 epan/dissectors/packet-tcp.c create mode 100644 epan/dissectors/packet-tcp.h create mode 100644 epan/dissectors/packet-tds.c create mode 100644 epan/dissectors/packet-teimanagement.c create mode 100644 epan/dissectors/packet-telnet.c create mode 100644 epan/dissectors/packet-teredo.c create mode 100644 epan/dissectors/packet-text-media.c create mode 100644 epan/dissectors/packet-tftp.c create mode 100644 epan/dissectors/packet-time.c create mode 100644 epan/dissectors/packet-tns.c create mode 100644 epan/dissectors/packet-tns.h create mode 100644 epan/dissectors/packet-tpkt.c create mode 100644 epan/dissectors/packet-tpkt.h create mode 100644 epan/dissectors/packet-tr.c create mode 100644 epan/dissectors/packet-tr.h create mode 100644 epan/dissectors/packet-trmac.c create mode 100644 epan/dissectors/packet-tsp.c create mode 100644 epan/dissectors/packet-tuxedo.c create mode 100644 epan/dissectors/packet-tzsp.c create mode 100644 epan/dissectors/packet-ucp.c create mode 100644 epan/dissectors/packet-udp.c create mode 100644 epan/dissectors/packet-udp.h create mode 100644 epan/dissectors/packet-v120.c create mode 100644 epan/dissectors/packet-vines.c create mode 100644 epan/dissectors/packet-vines.h create mode 100644 epan/dissectors/packet-vj.c create mode 100644 epan/dissectors/packet-vlan.c create mode 100644 epan/dissectors/packet-vlan.h create mode 100644 epan/dissectors/packet-vrrp.c create mode 100644 epan/dissectors/packet-vtp.c create mode 100644 epan/dissectors/packet-wap.c create mode 100644 epan/dissectors/packet-wap.h create mode 100644 epan/dissectors/packet-wbxml.c create mode 100644 epan/dissectors/packet-wccp.c create mode 100644 epan/dissectors/packet-wccp.h create mode 100644 epan/dissectors/packet-wcp.c create mode 100644 epan/dissectors/packet-wfleet-hdlc.c create mode 100644 epan/dissectors/packet-who.c create mode 100644 epan/dissectors/packet-wlancap.c create mode 100644 epan/dissectors/packet-wlancap.h create mode 100644 epan/dissectors/packet-wsp.c create mode 100644 epan/dissectors/packet-wsp.h create mode 100644 epan/dissectors/packet-wtls.c create mode 100644 epan/dissectors/packet-wtls.h create mode 100644 epan/dissectors/packet-wtp.c create mode 100644 epan/dissectors/packet-wtp.h create mode 100644 epan/dissectors/packet-x11-keysym.h create mode 100644 epan/dissectors/packet-x11-keysymdef.h create mode 100644 epan/dissectors/packet-x11.c create mode 100644 epan/dissectors/packet-x25.c create mode 100644 epan/dissectors/packet-x29.c create mode 100644 epan/dissectors/packet-xdmcp.c create mode 100644 epan/dissectors/packet-xot.c create mode 100644 epan/dissectors/packet-xyplex.c create mode 100644 epan/dissectors/packet-yhoo.c create mode 100644 epan/dissectors/packet-ymsg.c create mode 100644 epan/dissectors/packet-ypbind.c create mode 100644 epan/dissectors/packet-ypbind.h create mode 100644 epan/dissectors/packet-yppasswd.c create mode 100644 epan/dissectors/packet-yppasswd.h create mode 100644 epan/dissectors/packet-ypserv.c create mode 100644 epan/dissectors/packet-ypserv.h create mode 100644 epan/dissectors/packet-ypxfr.c create mode 100644 epan/dissectors/packet-ypxfr.h create mode 100644 epan/dissectors/packet-zebra.c create mode 100644 epan/dissectors/process-x11-fields.pl create mode 100644 epan/dissectors/x11-fields (limited to 'epan/dissectors') 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 +# 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 +# Copyright 1998 Gerald Combs +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public 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"^(?Pproto_register_[_A-Za-z0-9]+)\s*\([^;]+$" +proto_regex1 = r"void\s+(?Pproto_register_[_A-Za-z0-9]+)\s*\([^;]+$" + +handoff_regex0 = r"^(?Pproto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$" +handoff_regex1 = r"void\s+(?Pproto_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 . +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 . +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 +#include +#include +#include +#include "ptvcursor.h" +#include "packet-ncp-int.h" +#include "packet-ncp-nmas.h" +#include +#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 + * packet-3g-a11.c was written based on 'packet-mip.c'. + * + * packet-mip.c + * Routines for Mobile IP dissection + * Copyright 2000, Stefan Raab + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include +#include + +#include + +/* 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) 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 + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * 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 +#include +#include +#include +#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 + * Heavily based in packet-imap.c, Copyright 1999, Richard Sharpe + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * 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 + +#include +#include +#include +#include + +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 +* +* Ethereal - Network traffic analyzer +* By Gerald Combs +* Copyright 1998 Gerald Combs +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include + +#include "packet-acse.h" +#include "packet-frame.h" +#include "prefs.h" + +#include + +#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= '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 ] + */ + 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_stringoffset + -*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 ] + */ + 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 +* +* Ethereal - Network traffic analyzer +* By Gerald Combs +* Copyright 1998 Gerald Combs +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public 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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * 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 + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include +#include +#include +#include +#include + +#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 + * .... + * ip1:2048 --> ip2:548 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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * Based on routines from tcpdump patches by + * Ken Hornstein + * 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 + * 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 + * Based on routines from tcpdump patches by + * Ken Hornstein + * 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 + * 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 + * Based on routines from tcpdump patches by + * Ken Hornstein + * 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 + * 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 + * Based on routines from tcpdump patches by + * Ken Hornstein + * 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 + * 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 + +#include +#include +#include +#include +#include + +#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" 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; itype == 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; itype == 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; itype == 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 ( itype == 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 + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * Copyright 2000, Ralf Hoelzer + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * Copyright 2000, Ralf Hoelzer + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * Copyright 2000, Ralf Hoelzer + * Copyright 2004, Devin Heitmueller + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * Copyright 2000, Ralf Hoelzer + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * Copyright 2000, Ralf Hoelzer + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#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 + * Copyright 2004, Jelmer Vernooij + * Copyright 2004, Devin Heitmueller + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include "isprint.h" + +#include +#include + +#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 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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include + +#include +#include +#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; icinfo, 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; icontent_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 + * In association with Telos Technology Inc. + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#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 + * 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 + +#include +#include +#include + +/* 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 + * 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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#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 + * In association with Telos Technology Inc. + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#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 + * In association with Telos Technology Inc. + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#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 + * 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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#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 , + * In association with Telos Technology Inc. + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * 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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include + +#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 , + * In association with Telos Technology Inc. + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write 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 +#endif +#include + +#include + +#include +#include +#include + +#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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include + +#include +#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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#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 ""; + 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 ""; + 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 ""; + + 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 ""; + + /* + * 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 = ""; + } + + 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 = ""; + } + + 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 + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * 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 +#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 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * 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 +#include + +/* + * 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 + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * 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 +#include +#include + +#include "etypes.h" +#include "ppptypes.h" +#include "aftypes.h" +#include "arcnet_pids.h" +#include +#include + +#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; icinfo, 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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include "oui.h" +#include + +#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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +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 , FH Dortmund + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * 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 +#include +#include + +#include + +#include + +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 , FH Dortmund + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * 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 +#include +#include + +#include + +#include + +#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 + * Modified 2001 Darren New 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 +#include +#include +#include +#include +#include +#include +#include +#include "prefs.h" +#include + +#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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 +#include +#include + +#include + +#include + +#include +#include +#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;itype == 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; i200){ + 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(ibitmask) { + 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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include + +#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 + * + * $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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include +#include +#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= 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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + +#include + +#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 + * Copyright 2004, Thomas Anders + * + * $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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#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 + */ + 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 + * 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 +#include + +#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 + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include "llcsaps.h" +#include "ppptypes.h" +#include "chdlctypes.h" +#include + +/* 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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include +#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 + * In association with Telos Technology Inc. + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#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 + * In association with Telos Technology Inc. + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#include + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include +/*#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> 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 , FH Dortmund + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * 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 +#include +#include +#include "prefs.h" +#include + +#include + +#include + +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 + +#include +#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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include + +#ifdef NEED_SNPRINTF_H +# include "snprintf.h" +#endif + +#include + +/* + * 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 + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 +#include + +#include +#include +#include + +#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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 +#include + +#include +#include + +/* + * 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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include "etypes.h" +#include "prefs.h" +#include "chdlctypes.h" +#include +#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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 +#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 + * 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 + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * + * This file created by Thierry Andry + * from nearly-the-same packet-raw.c created by Mike Hall + * 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 +#include +#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 + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 + * Ralf Schneider + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include +#include "prefs.h" +#include +#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 MAX_TSAP_LEN) + sprintf(cur, ""); + 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<