print-juniper.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508
  1. /* NetBSD: print-juniper.c,v 1.2 2007/07/24 11:53:45 drochner Exp */
  2. /*
  3. * Redistribution and use in source and binary forms, with or without
  4. * modification, are permitted provided that: (1) source code
  5. * distributions retain the above copyright notice and this paragraph
  6. * in its entirety, and (2) distributions including binary code include
  7. * the above copyright notice and this paragraph in its entirety in
  8. * the documentation or other materials provided with the distribution.
  9. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
  10. * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
  11. * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  12. * FOR A PARTICULAR PURPOSE.
  13. *
  14. * Original code by Hannes Gredler (hannes@gredler.at)
  15. */
  16. /* \summary: DLT_JUNIPER_* printers */
  17. #ifndef lint
  18. #else
  19. __RCSID("NetBSD: print-juniper.c,v 1.3 2007/07/25 06:31:32 dogcow Exp ");
  20. #endif
  21. #ifdef HAVE_CONFIG_H
  22. #include "config.h"
  23. #endif
  24. #include <netdissect-stdinc.h>
  25. #include <string.h>
  26. #include "netdissect.h"
  27. #include "addrtoname.h"
  28. #include "extract.h"
  29. #include "ppp.h"
  30. #include "llc.h"
  31. #include "nlpid.h"
  32. #include "ethertype.h"
  33. #include "atm.h"
  34. #define JUNIPER_BPF_OUT 0 /* Outgoing packet */
  35. #define JUNIPER_BPF_IN 1 /* Incoming packet */
  36. #define JUNIPER_BPF_PKT_IN 0x1 /* Incoming packet */
  37. #define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */
  38. #define JUNIPER_BPF_IIF 0x4 /* IIF is valid */
  39. #define JUNIPER_BPF_FILTER 0x40 /* BPF filtering is supported */
  40. #define JUNIPER_BPF_EXT 0x80 /* extensions present */
  41. #define JUNIPER_MGC_NUMBER 0x4d4743 /* = "MGC" */
  42. #define JUNIPER_LSQ_COOKIE_RE (1 << 3)
  43. #define JUNIPER_LSQ_COOKIE_DIR (1 << 2)
  44. #define JUNIPER_LSQ_L3_PROTO_SHIFT 4
  45. #define JUNIPER_LSQ_L3_PROTO_MASK (0x17 << JUNIPER_LSQ_L3_PROTO_SHIFT)
  46. #define JUNIPER_LSQ_L3_PROTO_IPV4 (0 << JUNIPER_LSQ_L3_PROTO_SHIFT)
  47. #define JUNIPER_LSQ_L3_PROTO_IPV6 (1 << JUNIPER_LSQ_L3_PROTO_SHIFT)
  48. #define JUNIPER_LSQ_L3_PROTO_MPLS (2 << JUNIPER_LSQ_L3_PROTO_SHIFT)
  49. #define JUNIPER_LSQ_L3_PROTO_ISO (3 << JUNIPER_LSQ_L3_PROTO_SHIFT)
  50. #define AS_PIC_COOKIE_LEN 8
  51. #define JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE 1
  52. #define JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE 2
  53. #define JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE 3
  54. #define JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE 4
  55. #define JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE 5
  56. static const struct tok juniper_ipsec_type_values[] = {
  57. { JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE, "ESP ENCR-AUTH" },
  58. { JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE, "ESP ENCR-AH AUTH" },
  59. { JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE, "ESP AUTH" },
  60. { JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE, "AH AUTH" },
  61. { JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE, "ESP ENCR" },
  62. { 0, NULL}
  63. };
  64. static const struct tok juniper_direction_values[] = {
  65. { JUNIPER_BPF_IN, "In"},
  66. { JUNIPER_BPF_OUT, "Out"},
  67. { 0, NULL}
  68. };
  69. /* codepoints for encoding extensions to a .pcap file */
  70. enum {
  71. JUNIPER_EXT_TLV_IFD_IDX = 1,
  72. JUNIPER_EXT_TLV_IFD_NAME = 2,
  73. JUNIPER_EXT_TLV_IFD_MEDIATYPE = 3,
  74. JUNIPER_EXT_TLV_IFL_IDX = 4,
  75. JUNIPER_EXT_TLV_IFL_UNIT = 5,
  76. JUNIPER_EXT_TLV_IFL_ENCAPS = 6,
  77. JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE = 7,
  78. JUNIPER_EXT_TLV_TTP_IFL_ENCAPS = 8
  79. };
  80. /* 1 byte type and 1-byte length */
  81. #define JUNIPER_EXT_TLV_OVERHEAD 2U
  82. static const struct tok jnx_ext_tlv_values[] = {
  83. { JUNIPER_EXT_TLV_IFD_IDX, "Device Interface Index" },
  84. { JUNIPER_EXT_TLV_IFD_NAME,"Device Interface Name" },
  85. { JUNIPER_EXT_TLV_IFD_MEDIATYPE, "Device Media Type" },
  86. { JUNIPER_EXT_TLV_IFL_IDX, "Logical Interface Index" },
  87. { JUNIPER_EXT_TLV_IFL_UNIT,"Logical Unit Number" },
  88. { JUNIPER_EXT_TLV_IFL_ENCAPS, "Logical Interface Encapsulation" },
  89. { JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE, "TTP derived Device Media Type" },
  90. { JUNIPER_EXT_TLV_TTP_IFL_ENCAPS, "TTP derived Logical Interface Encapsulation" },
  91. { 0, NULL }
  92. };
  93. static const struct tok jnx_flag_values[] = {
  94. { JUNIPER_BPF_EXT, "Ext" },
  95. { JUNIPER_BPF_FILTER, "Filter" },
  96. { JUNIPER_BPF_IIF, "IIF" },
  97. { JUNIPER_BPF_NO_L2, "no-L2" },
  98. { JUNIPER_BPF_PKT_IN, "In" },
  99. { 0, NULL }
  100. };
  101. #define JUNIPER_IFML_ETHER 1
  102. #define JUNIPER_IFML_FDDI 2
  103. #define JUNIPER_IFML_TOKENRING 3
  104. #define JUNIPER_IFML_PPP 4
  105. #define JUNIPER_IFML_FRAMERELAY 5
  106. #define JUNIPER_IFML_CISCOHDLC 6
  107. #define JUNIPER_IFML_SMDSDXI 7
  108. #define JUNIPER_IFML_ATMPVC 8
  109. #define JUNIPER_IFML_PPP_CCC 9
  110. #define JUNIPER_IFML_FRAMERELAY_CCC 10
  111. #define JUNIPER_IFML_IPIP 11
  112. #define JUNIPER_IFML_GRE 12
  113. #define JUNIPER_IFML_PIM 13
  114. #define JUNIPER_IFML_PIMD 14
  115. #define JUNIPER_IFML_CISCOHDLC_CCC 15
  116. #define JUNIPER_IFML_VLAN_CCC 16
  117. #define JUNIPER_IFML_MLPPP 17
  118. #define JUNIPER_IFML_MLFR 18
  119. #define JUNIPER_IFML_ML 19
  120. #define JUNIPER_IFML_LSI 20
  121. #define JUNIPER_IFML_DFE 21
  122. #define JUNIPER_IFML_ATM_CELLRELAY_CCC 22
  123. #define JUNIPER_IFML_CRYPTO 23
  124. #define JUNIPER_IFML_GGSN 24
  125. #define JUNIPER_IFML_LSI_PPP 25
  126. #define JUNIPER_IFML_LSI_CISCOHDLC 26
  127. #define JUNIPER_IFML_PPP_TCC 27
  128. #define JUNIPER_IFML_FRAMERELAY_TCC 28
  129. #define JUNIPER_IFML_CISCOHDLC_TCC 29
  130. #define JUNIPER_IFML_ETHERNET_CCC 30
  131. #define JUNIPER_IFML_VT 31
  132. #define JUNIPER_IFML_EXTENDED_VLAN_CCC 32
  133. #define JUNIPER_IFML_ETHER_OVER_ATM 33
  134. #define JUNIPER_IFML_MONITOR 34
  135. #define JUNIPER_IFML_ETHERNET_TCC 35
  136. #define JUNIPER_IFML_VLAN_TCC 36
  137. #define JUNIPER_IFML_EXTENDED_VLAN_TCC 37
  138. #define JUNIPER_IFML_CONTROLLER 38
  139. #define JUNIPER_IFML_MFR 39
  140. #define JUNIPER_IFML_LS 40
  141. #define JUNIPER_IFML_ETHERNET_VPLS 41
  142. #define JUNIPER_IFML_ETHERNET_VLAN_VPLS 42
  143. #define JUNIPER_IFML_ETHERNET_EXTENDED_VLAN_VPLS 43
  144. #define JUNIPER_IFML_LT 44
  145. #define JUNIPER_IFML_SERVICES 45
  146. #define JUNIPER_IFML_ETHER_VPLS_OVER_ATM 46
  147. #define JUNIPER_IFML_FR_PORT_CCC 47
  148. #define JUNIPER_IFML_FRAMERELAY_EXT_CCC 48
  149. #define JUNIPER_IFML_FRAMERELAY_EXT_TCC 49
  150. #define JUNIPER_IFML_FRAMERELAY_FLEX 50
  151. #define JUNIPER_IFML_GGSNI 51
  152. #define JUNIPER_IFML_ETHERNET_FLEX 52
  153. #define JUNIPER_IFML_COLLECTOR 53
  154. #define JUNIPER_IFML_AGGREGATOR 54
  155. #define JUNIPER_IFML_LAPD 55
  156. #define JUNIPER_IFML_PPPOE 56
  157. #define JUNIPER_IFML_PPP_SUBORDINATE 57
  158. #define JUNIPER_IFML_CISCOHDLC_SUBORDINATE 58
  159. #define JUNIPER_IFML_DFC 59
  160. #define JUNIPER_IFML_PICPEER 60
  161. static const struct tok juniper_ifmt_values[] = {
  162. { JUNIPER_IFML_ETHER, "Ethernet" },
  163. { JUNIPER_IFML_FDDI, "FDDI" },
  164. { JUNIPER_IFML_TOKENRING, "Token-Ring" },
  165. { JUNIPER_IFML_PPP, "PPP" },
  166. { JUNIPER_IFML_PPP_SUBORDINATE, "PPP-Subordinate" },
  167. { JUNIPER_IFML_FRAMERELAY, "Frame-Relay" },
  168. { JUNIPER_IFML_CISCOHDLC, "Cisco-HDLC" },
  169. { JUNIPER_IFML_SMDSDXI, "SMDS-DXI" },
  170. { JUNIPER_IFML_ATMPVC, "ATM-PVC" },
  171. { JUNIPER_IFML_PPP_CCC, "PPP-CCC" },
  172. { JUNIPER_IFML_FRAMERELAY_CCC, "Frame-Relay-CCC" },
  173. { JUNIPER_IFML_FRAMERELAY_EXT_CCC, "Extended FR-CCC" },
  174. { JUNIPER_IFML_IPIP, "IP-over-IP" },
  175. { JUNIPER_IFML_GRE, "GRE" },
  176. { JUNIPER_IFML_PIM, "PIM-Encapsulator" },
  177. { JUNIPER_IFML_PIMD, "PIM-Decapsulator" },
  178. { JUNIPER_IFML_CISCOHDLC_CCC, "Cisco-HDLC-CCC" },
  179. { JUNIPER_IFML_VLAN_CCC, "VLAN-CCC" },
  180. { JUNIPER_IFML_EXTENDED_VLAN_CCC, "Extended-VLAN-CCC" },
  181. { JUNIPER_IFML_MLPPP, "Multilink-PPP" },
  182. { JUNIPER_IFML_MLFR, "Multilink-FR" },
  183. { JUNIPER_IFML_MFR, "Multilink-FR-UNI-NNI" },
  184. { JUNIPER_IFML_ML, "Multilink" },
  185. { JUNIPER_IFML_LS, "LinkService" },
  186. { JUNIPER_IFML_LSI, "LSI" },
  187. { JUNIPER_IFML_ATM_CELLRELAY_CCC, "ATM-CCC-Cell-Relay" },
  188. { JUNIPER_IFML_CRYPTO, "IPSEC-over-IP" },
  189. { JUNIPER_IFML_GGSN, "GGSN" },
  190. { JUNIPER_IFML_PPP_TCC, "PPP-TCC" },
  191. { JUNIPER_IFML_FRAMERELAY_TCC, "Frame-Relay-TCC" },
  192. { JUNIPER_IFML_FRAMERELAY_EXT_TCC, "Extended FR-TCC" },
  193. { JUNIPER_IFML_CISCOHDLC_TCC, "Cisco-HDLC-TCC" },
  194. { JUNIPER_IFML_ETHERNET_CCC, "Ethernet-CCC" },
  195. { JUNIPER_IFML_VT, "VPN-Loopback-tunnel" },
  196. { JUNIPER_IFML_ETHER_OVER_ATM, "Ethernet-over-ATM" },
  197. { JUNIPER_IFML_ETHER_VPLS_OVER_ATM, "Ethernet-VPLS-over-ATM" },
  198. { JUNIPER_IFML_MONITOR, "Monitor" },
  199. { JUNIPER_IFML_ETHERNET_TCC, "Ethernet-TCC" },
  200. { JUNIPER_IFML_VLAN_TCC, "VLAN-TCC" },
  201. { JUNIPER_IFML_EXTENDED_VLAN_TCC, "Extended-VLAN-TCC" },
  202. { JUNIPER_IFML_CONTROLLER, "Controller" },
  203. { JUNIPER_IFML_ETHERNET_VPLS, "VPLS" },
  204. { JUNIPER_IFML_ETHERNET_VLAN_VPLS, "VLAN-VPLS" },
  205. { JUNIPER_IFML_ETHERNET_EXTENDED_VLAN_VPLS, "Extended-VLAN-VPLS" },
  206. { JUNIPER_IFML_LT, "Logical-tunnel" },
  207. { JUNIPER_IFML_SERVICES, "General-Services" },
  208. { JUNIPER_IFML_PPPOE, "PPPoE" },
  209. { JUNIPER_IFML_ETHERNET_FLEX, "Flexible-Ethernet-Services" },
  210. { JUNIPER_IFML_FRAMERELAY_FLEX, "Flexible-FrameRelay" },
  211. { JUNIPER_IFML_COLLECTOR, "Flow-collection" },
  212. { JUNIPER_IFML_PICPEER, "PIC Peer" },
  213. { JUNIPER_IFML_DFC, "Dynamic-Flow-Capture" },
  214. {0, NULL}
  215. };
  216. #define JUNIPER_IFLE_ATM_SNAP 2
  217. #define JUNIPER_IFLE_ATM_NLPID 3
  218. #define JUNIPER_IFLE_ATM_VCMUX 4
  219. #define JUNIPER_IFLE_ATM_LLC 5
  220. #define JUNIPER_IFLE_ATM_PPP_VCMUX 6
  221. #define JUNIPER_IFLE_ATM_PPP_LLC 7
  222. #define JUNIPER_IFLE_ATM_PPP_FUNI 8
  223. #define JUNIPER_IFLE_ATM_CCC 9
  224. #define JUNIPER_IFLE_FR_NLPID 10
  225. #define JUNIPER_IFLE_FR_SNAP 11
  226. #define JUNIPER_IFLE_FR_PPP 12
  227. #define JUNIPER_IFLE_FR_CCC 13
  228. #define JUNIPER_IFLE_ENET2 14
  229. #define JUNIPER_IFLE_IEEE8023_SNAP 15
  230. #define JUNIPER_IFLE_IEEE8023_LLC 16
  231. #define JUNIPER_IFLE_PPP 17
  232. #define JUNIPER_IFLE_CISCOHDLC 18
  233. #define JUNIPER_IFLE_PPP_CCC 19
  234. #define JUNIPER_IFLE_IPIP_NULL 20
  235. #define JUNIPER_IFLE_PIM_NULL 21
  236. #define JUNIPER_IFLE_GRE_NULL 22
  237. #define JUNIPER_IFLE_GRE_PPP 23
  238. #define JUNIPER_IFLE_PIMD_DECAPS 24
  239. #define JUNIPER_IFLE_CISCOHDLC_CCC 25
  240. #define JUNIPER_IFLE_ATM_CISCO_NLPID 26
  241. #define JUNIPER_IFLE_VLAN_CCC 27
  242. #define JUNIPER_IFLE_MLPPP 28
  243. #define JUNIPER_IFLE_MLFR 29
  244. #define JUNIPER_IFLE_LSI_NULL 30
  245. #define JUNIPER_IFLE_AGGREGATE_UNUSED 31
  246. #define JUNIPER_IFLE_ATM_CELLRELAY_CCC 32
  247. #define JUNIPER_IFLE_CRYPTO 33
  248. #define JUNIPER_IFLE_GGSN 34
  249. #define JUNIPER_IFLE_ATM_TCC 35
  250. #define JUNIPER_IFLE_FR_TCC 36
  251. #define JUNIPER_IFLE_PPP_TCC 37
  252. #define JUNIPER_IFLE_CISCOHDLC_TCC 38
  253. #define JUNIPER_IFLE_ETHERNET_CCC 39
  254. #define JUNIPER_IFLE_VT 40
  255. #define JUNIPER_IFLE_ATM_EOA_LLC 41
  256. #define JUNIPER_IFLE_EXTENDED_VLAN_CCC 42
  257. #define JUNIPER_IFLE_ATM_SNAP_TCC 43
  258. #define JUNIPER_IFLE_MONITOR 44
  259. #define JUNIPER_IFLE_ETHERNET_TCC 45
  260. #define JUNIPER_IFLE_VLAN_TCC 46
  261. #define JUNIPER_IFLE_EXTENDED_VLAN_TCC 47
  262. #define JUNIPER_IFLE_MFR 48
  263. #define JUNIPER_IFLE_ETHERNET_VPLS 49
  264. #define JUNIPER_IFLE_ETHERNET_VLAN_VPLS 50
  265. #define JUNIPER_IFLE_ETHERNET_EXTENDED_VLAN_VPLS 51
  266. #define JUNIPER_IFLE_SERVICES 52
  267. #define JUNIPER_IFLE_ATM_ETHER_VPLS_ATM_LLC 53
  268. #define JUNIPER_IFLE_FR_PORT_CCC 54
  269. #define JUNIPER_IFLE_ATM_MLPPP_LLC 55
  270. #define JUNIPER_IFLE_ATM_EOA_CCC 56
  271. #define JUNIPER_IFLE_LT_VLAN 57
  272. #define JUNIPER_IFLE_COLLECTOR 58
  273. #define JUNIPER_IFLE_AGGREGATOR 59
  274. #define JUNIPER_IFLE_LAPD 60
  275. #define JUNIPER_IFLE_ATM_PPPOE_LLC 61
  276. #define JUNIPER_IFLE_ETHERNET_PPPOE 62
  277. #define JUNIPER_IFLE_PPPOE 63
  278. #define JUNIPER_IFLE_PPP_SUBORDINATE 64
  279. #define JUNIPER_IFLE_CISCOHDLC_SUBORDINATE 65
  280. #define JUNIPER_IFLE_DFC 66
  281. #define JUNIPER_IFLE_PICPEER 67
  282. static const struct tok juniper_ifle_values[] = {
  283. { JUNIPER_IFLE_AGGREGATOR, "Aggregator" },
  284. { JUNIPER_IFLE_ATM_CCC, "CCC over ATM" },
  285. { JUNIPER_IFLE_ATM_CELLRELAY_CCC, "ATM CCC Cell Relay" },
  286. { JUNIPER_IFLE_ATM_CISCO_NLPID, "CISCO compatible NLPID" },
  287. { JUNIPER_IFLE_ATM_EOA_CCC, "Ethernet over ATM CCC" },
  288. { JUNIPER_IFLE_ATM_EOA_LLC, "Ethernet over ATM LLC" },
  289. { JUNIPER_IFLE_ATM_ETHER_VPLS_ATM_LLC, "Ethernet VPLS over ATM LLC" },
  290. { JUNIPER_IFLE_ATM_LLC, "ATM LLC" },
  291. { JUNIPER_IFLE_ATM_MLPPP_LLC, "MLPPP over ATM LLC" },
  292. { JUNIPER_IFLE_ATM_NLPID, "ATM NLPID" },
  293. { JUNIPER_IFLE_ATM_PPPOE_LLC, "PPPoE over ATM LLC" },
  294. { JUNIPER_IFLE_ATM_PPP_FUNI, "PPP over FUNI" },
  295. { JUNIPER_IFLE_ATM_PPP_LLC, "PPP over ATM LLC" },
  296. { JUNIPER_IFLE_ATM_PPP_VCMUX, "PPP over ATM VCMUX" },
  297. { JUNIPER_IFLE_ATM_SNAP, "ATM SNAP" },
  298. { JUNIPER_IFLE_ATM_SNAP_TCC, "ATM SNAP TCC" },
  299. { JUNIPER_IFLE_ATM_TCC, "ATM VCMUX TCC" },
  300. { JUNIPER_IFLE_ATM_VCMUX, "ATM VCMUX" },
  301. { JUNIPER_IFLE_CISCOHDLC, "C-HDLC" },
  302. { JUNIPER_IFLE_CISCOHDLC_CCC, "C-HDLC CCC" },
  303. { JUNIPER_IFLE_CISCOHDLC_SUBORDINATE, "C-HDLC via dialer" },
  304. { JUNIPER_IFLE_CISCOHDLC_TCC, "C-HDLC TCC" },
  305. { JUNIPER_IFLE_COLLECTOR, "Collector" },
  306. { JUNIPER_IFLE_CRYPTO, "Crypto" },
  307. { JUNIPER_IFLE_ENET2, "Ethernet" },
  308. { JUNIPER_IFLE_ETHERNET_CCC, "Ethernet CCC" },
  309. { JUNIPER_IFLE_ETHERNET_EXTENDED_VLAN_VPLS, "Extended VLAN VPLS" },
  310. { JUNIPER_IFLE_ETHERNET_PPPOE, "PPPoE over Ethernet" },
  311. { JUNIPER_IFLE_ETHERNET_TCC, "Ethernet TCC" },
  312. { JUNIPER_IFLE_ETHERNET_VLAN_VPLS, "VLAN VPLS" },
  313. { JUNIPER_IFLE_ETHERNET_VPLS, "VPLS" },
  314. { JUNIPER_IFLE_EXTENDED_VLAN_CCC, "Extended VLAN CCC" },
  315. { JUNIPER_IFLE_EXTENDED_VLAN_TCC, "Extended VLAN TCC" },
  316. { JUNIPER_IFLE_FR_CCC, "FR CCC" },
  317. { JUNIPER_IFLE_FR_NLPID, "FR NLPID" },
  318. { JUNIPER_IFLE_FR_PORT_CCC, "FR CCC" },
  319. { JUNIPER_IFLE_FR_PPP, "FR PPP" },
  320. { JUNIPER_IFLE_FR_SNAP, "FR SNAP" },
  321. { JUNIPER_IFLE_FR_TCC, "FR TCC" },
  322. { JUNIPER_IFLE_GGSN, "GGSN" },
  323. { JUNIPER_IFLE_GRE_NULL, "GRE NULL" },
  324. { JUNIPER_IFLE_GRE_PPP, "PPP over GRE" },
  325. { JUNIPER_IFLE_IPIP_NULL, "IPIP" },
  326. { JUNIPER_IFLE_LAPD, "LAPD" },
  327. { JUNIPER_IFLE_LSI_NULL, "LSI Null" },
  328. { JUNIPER_IFLE_LT_VLAN, "LT VLAN" },
  329. { JUNIPER_IFLE_MFR, "MFR" },
  330. { JUNIPER_IFLE_MLFR, "MLFR" },
  331. { JUNIPER_IFLE_MLPPP, "MLPPP" },
  332. { JUNIPER_IFLE_MONITOR, "Monitor" },
  333. { JUNIPER_IFLE_PIMD_DECAPS, "PIMd" },
  334. { JUNIPER_IFLE_PIM_NULL, "PIM Null" },
  335. { JUNIPER_IFLE_PPP, "PPP" },
  336. { JUNIPER_IFLE_PPPOE, "PPPoE" },
  337. { JUNIPER_IFLE_PPP_CCC, "PPP CCC" },
  338. { JUNIPER_IFLE_PPP_SUBORDINATE, "" },
  339. { JUNIPER_IFLE_PPP_TCC, "PPP TCC" },
  340. { JUNIPER_IFLE_SERVICES, "General Services" },
  341. { JUNIPER_IFLE_VLAN_CCC, "VLAN CCC" },
  342. { JUNIPER_IFLE_VLAN_TCC, "VLAN TCC" },
  343. { JUNIPER_IFLE_VT, "VT" },
  344. {0, NULL}
  345. };
  346. struct juniper_cookie_table_t {
  347. uint32_t pictype; /* pic type */
  348. uint8_t cookie_len; /* cookie len */
  349. const char *s; /* pic name */
  350. };
  351. static const struct juniper_cookie_table_t juniper_cookie_table[] = {
  352. #ifdef DLT_JUNIPER_ATM1
  353. { DLT_JUNIPER_ATM1, 4, "ATM1"},
  354. #endif
  355. #ifdef DLT_JUNIPER_ATM2
  356. { DLT_JUNIPER_ATM2, 8, "ATM2"},
  357. #endif
  358. #ifdef DLT_JUNIPER_MLPPP
  359. { DLT_JUNIPER_MLPPP, 2, "MLPPP"},
  360. #endif
  361. #ifdef DLT_JUNIPER_MLFR
  362. { DLT_JUNIPER_MLFR, 2, "MLFR"},
  363. #endif
  364. #ifdef DLT_JUNIPER_MFR
  365. { DLT_JUNIPER_MFR, 4, "MFR"},
  366. #endif
  367. #ifdef DLT_JUNIPER_PPPOE
  368. { DLT_JUNIPER_PPPOE, 0, "PPPoE"},
  369. #endif
  370. #ifdef DLT_JUNIPER_PPPOE_ATM
  371. { DLT_JUNIPER_PPPOE_ATM, 0, "PPPoE ATM"},
  372. #endif
  373. #ifdef DLT_JUNIPER_GGSN
  374. { DLT_JUNIPER_GGSN, 8, "GGSN"},
  375. #endif
  376. #ifdef DLT_JUNIPER_MONITOR
  377. { DLT_JUNIPER_MONITOR, 8, "MONITOR"},
  378. #endif
  379. #ifdef DLT_JUNIPER_SERVICES
  380. { DLT_JUNIPER_SERVICES, 8, "AS"},
  381. #endif
  382. #ifdef DLT_JUNIPER_ES
  383. { DLT_JUNIPER_ES, 0, "ES"},
  384. #endif
  385. { 0, 0, NULL }
  386. };
  387. struct juniper_l2info_t {
  388. uint32_t length;
  389. uint32_t caplen;
  390. uint32_t pictype;
  391. uint8_t direction;
  392. uint8_t header_len;
  393. uint8_t cookie_len;
  394. uint8_t cookie_type;
  395. uint8_t cookie[8];
  396. uint8_t bundle;
  397. uint16_t proto;
  398. uint8_t flags;
  399. };
  400. #define LS_COOKIE_ID 0x54
  401. #define AS_COOKIE_ID 0x47
  402. #define LS_MLFR_COOKIE_LEN 4
  403. #define ML_MLFR_COOKIE_LEN 2
  404. #define LS_MFR_COOKIE_LEN 6
  405. #define ATM1_COOKIE_LEN 4
  406. #define ATM2_COOKIE_LEN 8
  407. #define ATM2_PKT_TYPE_MASK 0x70
  408. #define ATM2_GAP_COUNT_MASK 0x3F
  409. #define JUNIPER_PROTO_NULL 1
  410. #define JUNIPER_PROTO_IPV4 2
  411. #define JUNIPER_PROTO_IPV6 6
  412. #define MFR_BE_MASK 0xc0
  413. static const struct tok juniper_protocol_values[] = {
  414. { JUNIPER_PROTO_NULL, "Null" },
  415. { JUNIPER_PROTO_IPV4, "IPv4" },
  416. { JUNIPER_PROTO_IPV6, "IPv6" },
  417. { 0, NULL}
  418. };
  419. static int ip_heuristic_guess(netdissect_options *, register const u_char *, u_int);
  420. static int juniper_ppp_heuristic_guess(netdissect_options *, register const u_char *, u_int);
  421. static int juniper_parse_header(netdissect_options *, const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *);
  422. #ifdef DLT_JUNIPER_GGSN
  423. u_int
  424. juniper_ggsn_print(netdissect_options *ndo,
  425. const struct pcap_pkthdr *h, register const u_char *p)
  426. {
  427. struct juniper_l2info_t l2info;
  428. struct juniper_ggsn_header {
  429. uint8_t svc_id;
  430. uint8_t flags_len;
  431. uint8_t proto;
  432. uint8_t flags;
  433. uint8_t vlan_id[2];
  434. uint8_t res[2];
  435. };
  436. const struct juniper_ggsn_header *gh;
  437. l2info.pictype = DLT_JUNIPER_GGSN;
  438. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  439. return l2info.header_len;
  440. p+=l2info.header_len;
  441. gh = (struct juniper_ggsn_header *)&l2info.cookie;
  442. ND_TCHECK(*gh);
  443. if (ndo->ndo_eflag) {
  444. ND_PRINT((ndo, "proto %s (%u), vlan %u: ",
  445. tok2str(juniper_protocol_values,"Unknown",gh->proto),
  446. gh->proto,
  447. EXTRACT_16BITS(&gh->vlan_id[0])));
  448. }
  449. switch (gh->proto) {
  450. case JUNIPER_PROTO_IPV4:
  451. ip_print(ndo, p, l2info.length);
  452. break;
  453. case JUNIPER_PROTO_IPV6:
  454. ip6_print(ndo, p, l2info.length);
  455. break;
  456. default:
  457. if (!ndo->ndo_eflag)
  458. ND_PRINT((ndo, "unknown GGSN proto (%u)", gh->proto));
  459. }
  460. return l2info.header_len;
  461. trunc:
  462. ND_PRINT((ndo, "[|juniper_services]"));
  463. return l2info.header_len;
  464. }
  465. #endif
  466. #ifdef DLT_JUNIPER_ES
  467. u_int
  468. juniper_es_print(netdissect_options *ndo,
  469. const struct pcap_pkthdr *h, register const u_char *p)
  470. {
  471. struct juniper_l2info_t l2info;
  472. struct juniper_ipsec_header {
  473. uint8_t sa_index[2];
  474. uint8_t ttl;
  475. uint8_t type;
  476. uint8_t spi[4];
  477. uint8_t src_ip[4];
  478. uint8_t dst_ip[4];
  479. };
  480. u_int rewrite_len,es_type_bundle;
  481. const struct juniper_ipsec_header *ih;
  482. l2info.pictype = DLT_JUNIPER_ES;
  483. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  484. return l2info.header_len;
  485. p+=l2info.header_len;
  486. ih = (const struct juniper_ipsec_header *)p;
  487. ND_TCHECK(*ih);
  488. switch (ih->type) {
  489. case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE:
  490. case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE:
  491. rewrite_len = 0;
  492. es_type_bundle = 1;
  493. break;
  494. case JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE:
  495. case JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE:
  496. case JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE:
  497. rewrite_len = 16;
  498. es_type_bundle = 0;
  499. break;
  500. default:
  501. ND_PRINT((ndo, "ES Invalid type %u, length %u",
  502. ih->type,
  503. l2info.length));
  504. return l2info.header_len;
  505. }
  506. l2info.length-=rewrite_len;
  507. p+=rewrite_len;
  508. if (ndo->ndo_eflag) {
  509. if (!es_type_bundle) {
  510. ND_PRINT((ndo, "ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n",
  511. EXTRACT_16BITS(&ih->sa_index),
  512. ih->ttl,
  513. tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
  514. ih->type,
  515. EXTRACT_32BITS(&ih->spi),
  516. ipaddr_string(ndo, &ih->src_ip),
  517. ipaddr_string(ndo, &ih->dst_ip),
  518. l2info.length));
  519. } else {
  520. ND_PRINT((ndo, "ES SA, index %u, ttl %u type %s (%u), length %u\n",
  521. EXTRACT_16BITS(&ih->sa_index),
  522. ih->ttl,
  523. tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
  524. ih->type,
  525. l2info.length));
  526. }
  527. }
  528. ip_print(ndo, p, l2info.length);
  529. return l2info.header_len;
  530. trunc:
  531. ND_PRINT((ndo, "[|juniper_services]"));
  532. return l2info.header_len;
  533. }
  534. #endif
  535. #ifdef DLT_JUNIPER_MONITOR
  536. u_int
  537. juniper_monitor_print(netdissect_options *ndo,
  538. const struct pcap_pkthdr *h, register const u_char *p)
  539. {
  540. struct juniper_l2info_t l2info;
  541. struct juniper_monitor_header {
  542. uint8_t pkt_type;
  543. uint8_t padding;
  544. uint8_t iif[2];
  545. uint8_t service_id[4];
  546. };
  547. const struct juniper_monitor_header *mh;
  548. l2info.pictype = DLT_JUNIPER_MONITOR;
  549. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  550. return l2info.header_len;
  551. p+=l2info.header_len;
  552. mh = (const struct juniper_monitor_header *)p;
  553. ND_TCHECK(*mh);
  554. if (ndo->ndo_eflag)
  555. ND_PRINT((ndo, "service-id %u, iif %u, pkt-type %u: ",
  556. EXTRACT_32BITS(&mh->service_id),
  557. EXTRACT_16BITS(&mh->iif),
  558. mh->pkt_type));
  559. /* no proto field - lets guess by first byte of IP header*/
  560. ip_heuristic_guess (ndo, p, l2info.length);
  561. return l2info.header_len;
  562. trunc:
  563. ND_PRINT((ndo, "[|juniper_services]"));
  564. return l2info.header_len;
  565. }
  566. #endif
  567. #ifdef DLT_JUNIPER_SERVICES
  568. u_int
  569. juniper_services_print(netdissect_options *ndo,
  570. const struct pcap_pkthdr *h, register const u_char *p)
  571. {
  572. struct juniper_l2info_t l2info;
  573. struct juniper_services_header {
  574. uint8_t svc_id;
  575. uint8_t flags_len;
  576. uint8_t svc_set_id[2];
  577. uint8_t dir_iif[4];
  578. };
  579. const struct juniper_services_header *sh;
  580. l2info.pictype = DLT_JUNIPER_SERVICES;
  581. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  582. return l2info.header_len;
  583. p+=l2info.header_len;
  584. sh = (const struct juniper_services_header *)p;
  585. ND_TCHECK(*sh);
  586. if (ndo->ndo_eflag)
  587. ND_PRINT((ndo, "service-id %u flags 0x%02x service-set-id 0x%04x iif %u: ",
  588. sh->svc_id,
  589. sh->flags_len,
  590. EXTRACT_16BITS(&sh->svc_set_id),
  591. EXTRACT_24BITS(&sh->dir_iif[1])));
  592. /* no proto field - lets guess by first byte of IP header*/
  593. ip_heuristic_guess (ndo, p, l2info.length);
  594. return l2info.header_len;
  595. trunc:
  596. ND_PRINT((ndo, "[|juniper_services]"));
  597. return l2info.header_len;
  598. }
  599. #endif
  600. #ifdef DLT_JUNIPER_PPPOE
  601. u_int
  602. juniper_pppoe_print(netdissect_options *ndo,
  603. const struct pcap_pkthdr *h, register const u_char *p)
  604. {
  605. struct juniper_l2info_t l2info;
  606. l2info.pictype = DLT_JUNIPER_PPPOE;
  607. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  608. return l2info.header_len;
  609. p+=l2info.header_len;
  610. /* this DLT contains nothing but raw ethernet frames */
  611. ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
  612. return l2info.header_len;
  613. }
  614. #endif
  615. #ifdef DLT_JUNIPER_ETHER
  616. u_int
  617. juniper_ether_print(netdissect_options *ndo,
  618. const struct pcap_pkthdr *h, register const u_char *p)
  619. {
  620. struct juniper_l2info_t l2info;
  621. l2info.pictype = DLT_JUNIPER_ETHER;
  622. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  623. return l2info.header_len;
  624. p+=l2info.header_len;
  625. /* this DLT contains nothing but raw Ethernet frames */
  626. ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
  627. return l2info.header_len;
  628. }
  629. #endif
  630. #ifdef DLT_JUNIPER_PPP
  631. u_int
  632. juniper_ppp_print(netdissect_options *ndo,
  633. const struct pcap_pkthdr *h, register const u_char *p)
  634. {
  635. struct juniper_l2info_t l2info;
  636. l2info.pictype = DLT_JUNIPER_PPP;
  637. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  638. return l2info.header_len;
  639. p+=l2info.header_len;
  640. /* this DLT contains nothing but raw ppp frames */
  641. ppp_print(ndo, p, l2info.length);
  642. return l2info.header_len;
  643. }
  644. #endif
  645. #ifdef DLT_JUNIPER_FRELAY
  646. u_int
  647. juniper_frelay_print(netdissect_options *ndo,
  648. const struct pcap_pkthdr *h, register const u_char *p)
  649. {
  650. struct juniper_l2info_t l2info;
  651. l2info.pictype = DLT_JUNIPER_FRELAY;
  652. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  653. return l2info.header_len;
  654. p+=l2info.header_len;
  655. /* this DLT contains nothing but raw frame-relay frames */
  656. fr_print(ndo, p, l2info.length);
  657. return l2info.header_len;
  658. }
  659. #endif
  660. #ifdef DLT_JUNIPER_CHDLC
  661. u_int
  662. juniper_chdlc_print(netdissect_options *ndo,
  663. const struct pcap_pkthdr *h, register const u_char *p)
  664. {
  665. struct juniper_l2info_t l2info;
  666. l2info.pictype = DLT_JUNIPER_CHDLC;
  667. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  668. return l2info.header_len;
  669. p+=l2info.header_len;
  670. /* this DLT contains nothing but raw c-hdlc frames */
  671. chdlc_print(ndo, p, l2info.length);
  672. return l2info.header_len;
  673. }
  674. #endif
  675. #ifdef DLT_JUNIPER_PPPOE_ATM
  676. u_int
  677. juniper_pppoe_atm_print(netdissect_options *ndo,
  678. const struct pcap_pkthdr *h, register const u_char *p)
  679. {
  680. struct juniper_l2info_t l2info;
  681. uint16_t extracted_ethertype;
  682. l2info.pictype = DLT_JUNIPER_PPPOE_ATM;
  683. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  684. return l2info.header_len;
  685. p+=l2info.header_len;
  686. ND_TCHECK2(p[0], 2);
  687. extracted_ethertype = EXTRACT_16BITS(p);
  688. /* this DLT contains nothing but raw PPPoE frames,
  689. * prepended with a type field*/
  690. if (ethertype_print(ndo, extracted_ethertype,
  691. p+ETHERTYPE_LEN,
  692. l2info.length-ETHERTYPE_LEN,
  693. l2info.caplen-ETHERTYPE_LEN,
  694. NULL, NULL) == 0)
  695. /* ether_type not known, probably it wasn't one */
  696. ND_PRINT((ndo, "unknown ethertype 0x%04x", extracted_ethertype));
  697. return l2info.header_len;
  698. trunc:
  699. ND_PRINT((ndo, "[|juniper_pppoe_atm]"));
  700. return l2info.header_len;
  701. }
  702. #endif
  703. #ifdef DLT_JUNIPER_MLPPP
  704. u_int
  705. juniper_mlppp_print(netdissect_options *ndo,
  706. const struct pcap_pkthdr *h, register const u_char *p)
  707. {
  708. struct juniper_l2info_t l2info;
  709. l2info.pictype = DLT_JUNIPER_MLPPP;
  710. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  711. return l2info.header_len;
  712. /* suppress Bundle-ID if frame was captured on a child-link
  713. * best indicator if the cookie looks like a proto */
  714. if (ndo->ndo_eflag &&
  715. EXTRACT_16BITS(&l2info.cookie) != PPP_OSI &&
  716. EXTRACT_16BITS(&l2info.cookie) != (PPP_ADDRESS << 8 | PPP_CONTROL))
  717. ND_PRINT((ndo, "Bundle-ID %u: ", l2info.bundle));
  718. p+=l2info.header_len;
  719. /* first try the LSQ protos */
  720. switch(l2info.proto) {
  721. case JUNIPER_LSQ_L3_PROTO_IPV4:
  722. /* IP traffic going to the RE would not have a cookie
  723. * -> this must be incoming IS-IS over PPP
  724. */
  725. if (l2info.cookie[4] == (JUNIPER_LSQ_COOKIE_RE|JUNIPER_LSQ_COOKIE_DIR))
  726. ppp_print(ndo, p, l2info.length);
  727. else
  728. ip_print(ndo, p, l2info.length);
  729. return l2info.header_len;
  730. case JUNIPER_LSQ_L3_PROTO_IPV6:
  731. ip6_print(ndo, p,l2info.length);
  732. return l2info.header_len;
  733. case JUNIPER_LSQ_L3_PROTO_MPLS:
  734. mpls_print(ndo, p, l2info.length);
  735. return l2info.header_len;
  736. case JUNIPER_LSQ_L3_PROTO_ISO:
  737. isoclns_print(ndo, p, l2info.length);
  738. return l2info.header_len;
  739. default:
  740. break;
  741. }
  742. /* zero length cookie ? */
  743. switch (EXTRACT_16BITS(&l2info.cookie)) {
  744. case PPP_OSI:
  745. ppp_print(ndo, p - 2, l2info.length + 2);
  746. break;
  747. case (PPP_ADDRESS << 8 | PPP_CONTROL): /* fall through */
  748. default:
  749. ppp_print(ndo, p, l2info.length);
  750. break;
  751. }
  752. return l2info.header_len;
  753. }
  754. #endif
  755. #ifdef DLT_JUNIPER_MFR
  756. u_int
  757. juniper_mfr_print(netdissect_options *ndo,
  758. const struct pcap_pkthdr *h, register const u_char *p)
  759. {
  760. struct juniper_l2info_t l2info;
  761. memset(&l2info, 0, sizeof(l2info));
  762. l2info.pictype = DLT_JUNIPER_MFR;
  763. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  764. return l2info.header_len;
  765. p+=l2info.header_len;
  766. /* child-link ? */
  767. if (l2info.cookie_len == 0) {
  768. mfr_print(ndo, p, l2info.length);
  769. return l2info.header_len;
  770. }
  771. /* first try the LSQ protos */
  772. if (l2info.cookie_len == AS_PIC_COOKIE_LEN) {
  773. switch(l2info.proto) {
  774. case JUNIPER_LSQ_L3_PROTO_IPV4:
  775. ip_print(ndo, p, l2info.length);
  776. return l2info.header_len;
  777. case JUNIPER_LSQ_L3_PROTO_IPV6:
  778. ip6_print(ndo, p,l2info.length);
  779. return l2info.header_len;
  780. case JUNIPER_LSQ_L3_PROTO_MPLS:
  781. mpls_print(ndo, p, l2info.length);
  782. return l2info.header_len;
  783. case JUNIPER_LSQ_L3_PROTO_ISO:
  784. isoclns_print(ndo, p, l2info.length);
  785. return l2info.header_len;
  786. default:
  787. break;
  788. }
  789. return l2info.header_len;
  790. }
  791. /* suppress Bundle-ID if frame was captured on a child-link */
  792. if (ndo->ndo_eflag && EXTRACT_32BITS(l2info.cookie) != 1)
  793. ND_PRINT((ndo, "Bundle-ID %u, ", l2info.bundle));
  794. switch (l2info.proto) {
  795. case (LLCSAP_ISONS<<8 | LLCSAP_ISONS):
  796. isoclns_print(ndo, p + 1, l2info.length - 1);
  797. break;
  798. case (LLC_UI<<8 | NLPID_Q933):
  799. case (LLC_UI<<8 | NLPID_IP):
  800. case (LLC_UI<<8 | NLPID_IP6):
  801. /* pass IP{4,6} to the OSI layer for proper link-layer printing */
  802. isoclns_print(ndo, p - 1, l2info.length + 1);
  803. break;
  804. default:
  805. ND_PRINT((ndo, "unknown protocol 0x%04x, length %u", l2info.proto, l2info.length));
  806. }
  807. return l2info.header_len;
  808. }
  809. #endif
  810. #ifdef DLT_JUNIPER_MLFR
  811. u_int
  812. juniper_mlfr_print(netdissect_options *ndo,
  813. const struct pcap_pkthdr *h, register const u_char *p)
  814. {
  815. struct juniper_l2info_t l2info;
  816. l2info.pictype = DLT_JUNIPER_MLFR;
  817. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  818. return l2info.header_len;
  819. p+=l2info.header_len;
  820. /* suppress Bundle-ID if frame was captured on a child-link */
  821. if (ndo->ndo_eflag && EXTRACT_32BITS(l2info.cookie) != 1)
  822. ND_PRINT((ndo, "Bundle-ID %u, ", l2info.bundle));
  823. switch (l2info.proto) {
  824. case (LLC_UI):
  825. case (LLC_UI<<8):
  826. isoclns_print(ndo, p, l2info.length);
  827. break;
  828. case (LLC_UI<<8 | NLPID_Q933):
  829. case (LLC_UI<<8 | NLPID_IP):
  830. case (LLC_UI<<8 | NLPID_IP6):
  831. /* pass IP{4,6} to the OSI layer for proper link-layer printing */
  832. isoclns_print(ndo, p - 1, l2info.length + 1);
  833. break;
  834. default:
  835. ND_PRINT((ndo, "unknown protocol 0x%04x, length %u", l2info.proto, l2info.length));
  836. }
  837. return l2info.header_len;
  838. }
  839. #endif
  840. /*
  841. * ATM1 PIC cookie format
  842. *
  843. * +-----+-------------------------+-------------------------------+
  844. * |fmtid| vc index | channel ID |
  845. * +-----+-------------------------+-------------------------------+
  846. */
  847. #ifdef DLT_JUNIPER_ATM1
  848. u_int
  849. juniper_atm1_print(netdissect_options *ndo,
  850. const struct pcap_pkthdr *h, register const u_char *p)
  851. {
  852. int llc_hdrlen;
  853. struct juniper_l2info_t l2info;
  854. l2info.pictype = DLT_JUNIPER_ATM1;
  855. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  856. return l2info.header_len;
  857. p+=l2info.header_len;
  858. if (l2info.cookie[0] == 0x80) { /* OAM cell ? */
  859. oam_print(ndo, p, l2info.length, ATM_OAM_NOHEC);
  860. return l2info.header_len;
  861. }
  862. ND_TCHECK2(p[0], 3);
  863. if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
  864. EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
  865. llc_hdrlen = llc_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
  866. if (llc_hdrlen > 0)
  867. return l2info.header_len;
  868. }
  869. if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
  870. isoclns_print(ndo, p + 1, l2info.length - 1);
  871. /* FIXME check if frame was recognized */
  872. return l2info.header_len;
  873. }
  874. if (ip_heuristic_guess(ndo, p, l2info.length) != 0) /* last try - vcmux encaps ? */
  875. return l2info.header_len;
  876. return l2info.header_len;
  877. trunc:
  878. ND_PRINT((ndo, "[|juniper_atm1]"));
  879. return l2info.header_len;
  880. }
  881. #endif
  882. /*
  883. * ATM2 PIC cookie format
  884. *
  885. * +-------------------------------+---------+---+-----+-----------+
  886. * | channel ID | reserv |AAL| CCRQ| gap cnt |
  887. * +-------------------------------+---------+---+-----+-----------+
  888. */
  889. #ifdef DLT_JUNIPER_ATM2
  890. u_int
  891. juniper_atm2_print(netdissect_options *ndo,
  892. const struct pcap_pkthdr *h, register const u_char *p)
  893. {
  894. int llc_hdrlen;
  895. struct juniper_l2info_t l2info;
  896. l2info.pictype = DLT_JUNIPER_ATM2;
  897. if (juniper_parse_header(ndo, p, h, &l2info) == 0)
  898. return l2info.header_len;
  899. p+=l2info.header_len;
  900. if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
  901. oam_print(ndo, p, l2info.length, ATM_OAM_NOHEC);
  902. return l2info.header_len;
  903. }
  904. ND_TCHECK2(p[0], 3);
  905. if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
  906. EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
  907. llc_hdrlen = llc_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
  908. if (llc_hdrlen > 0)
  909. return l2info.header_len;
  910. }
  911. if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
  912. (EXTRACT_32BITS(l2info.cookie) & ATM2_GAP_COUNT_MASK)) {
  913. ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
  914. return l2info.header_len;
  915. }
  916. if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
  917. isoclns_print(ndo, p + 1, l2info.length - 1);
  918. /* FIXME check if frame was recognized */
  919. return l2info.header_len;
  920. }
  921. if(juniper_ppp_heuristic_guess(ndo, p, l2info.length) != 0) /* PPPoA vcmux encaps ? */
  922. return l2info.header_len;
  923. if (ip_heuristic_guess(ndo, p, l2info.length) != 0) /* last try - vcmux encaps ? */
  924. return l2info.header_len;
  925. return l2info.header_len;
  926. trunc:
  927. ND_PRINT((ndo, "[|juniper_atm2]"));
  928. return l2info.header_len;
  929. }
  930. #endif
  931. /* try to guess, based on all PPP protos that are supported in
  932. * a juniper router if the payload data is encapsulated using PPP */
  933. static int
  934. juniper_ppp_heuristic_guess(netdissect_options *ndo,
  935. register const u_char *p, u_int length)
  936. {
  937. switch(EXTRACT_16BITS(p)) {
  938. case PPP_IP :
  939. case PPP_OSI :
  940. case PPP_MPLS_UCAST :
  941. case PPP_MPLS_MCAST :
  942. case PPP_IPCP :
  943. case PPP_OSICP :
  944. case PPP_MPLSCP :
  945. case PPP_LCP :
  946. case PPP_PAP :
  947. case PPP_CHAP :
  948. case PPP_ML :
  949. case PPP_IPV6 :
  950. case PPP_IPV6CP :
  951. ppp_print(ndo, p, length);
  952. break;
  953. default:
  954. return 0; /* did not find a ppp header */
  955. break;
  956. }
  957. return 1; /* we printed a ppp packet */
  958. }
  959. static int
  960. ip_heuristic_guess(netdissect_options *ndo,
  961. register const u_char *p, u_int length)
  962. {
  963. switch(p[0]) {
  964. case 0x45:
  965. case 0x46:
  966. case 0x47:
  967. case 0x48:
  968. case 0x49:
  969. case 0x4a:
  970. case 0x4b:
  971. case 0x4c:
  972. case 0x4d:
  973. case 0x4e:
  974. case 0x4f:
  975. ip_print(ndo, p, length);
  976. break;
  977. case 0x60:
  978. case 0x61:
  979. case 0x62:
  980. case 0x63:
  981. case 0x64:
  982. case 0x65:
  983. case 0x66:
  984. case 0x67:
  985. case 0x68:
  986. case 0x69:
  987. case 0x6a:
  988. case 0x6b:
  989. case 0x6c:
  990. case 0x6d:
  991. case 0x6e:
  992. case 0x6f:
  993. ip6_print(ndo, p, length);
  994. break;
  995. default:
  996. return 0; /* did not find a ip header */
  997. break;
  998. }
  999. return 1; /* we printed an v4/v6 packet */
  1000. }
  1001. static int
  1002. juniper_read_tlv_value(const u_char *p, u_int tlv_type, u_int tlv_len)
  1003. {
  1004. int tlv_value;
  1005. /* TLVs < 128 are little endian encoded */
  1006. if (tlv_type < 128) {
  1007. switch (tlv_len) {
  1008. case 1:
  1009. tlv_value = *p;
  1010. break;
  1011. case 2:
  1012. tlv_value = EXTRACT_LE_16BITS(p);
  1013. break;
  1014. case 3:
  1015. tlv_value = EXTRACT_LE_24BITS(p);
  1016. break;
  1017. case 4:
  1018. tlv_value = EXTRACT_LE_32BITS(p);
  1019. break;
  1020. default:
  1021. tlv_value = -1;
  1022. break;
  1023. }
  1024. } else {
  1025. /* TLVs >= 128 are big endian encoded */
  1026. switch (tlv_len) {
  1027. case 1:
  1028. tlv_value = *p;
  1029. break;
  1030. case 2:
  1031. tlv_value = EXTRACT_16BITS(p);
  1032. break;
  1033. case 3:
  1034. tlv_value = EXTRACT_24BITS(p);
  1035. break;
  1036. case 4:
  1037. tlv_value = EXTRACT_32BITS(p);
  1038. break;
  1039. default:
  1040. tlv_value = -1;
  1041. break;
  1042. }
  1043. }
  1044. return tlv_value;
  1045. }
  1046. static int
  1047. juniper_parse_header(netdissect_options *ndo,
  1048. const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info)
  1049. {
  1050. const struct juniper_cookie_table_t *lp = juniper_cookie_table;
  1051. u_int idx, jnx_ext_len, jnx_header_len = 0;
  1052. uint8_t tlv_type,tlv_len;
  1053. uint32_t control_word;
  1054. int tlv_value;
  1055. const u_char *tptr;
  1056. l2info->header_len = 0;
  1057. l2info->cookie_len = 0;
  1058. l2info->proto = 0;
  1059. l2info->length = h->len;
  1060. l2info->caplen = h->caplen;
  1061. ND_TCHECK2(p[0], 4);
  1062. l2info->flags = p[3];
  1063. l2info->direction = p[3]&JUNIPER_BPF_PKT_IN;
  1064. if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) { /* magic number found ? */
  1065. ND_PRINT((ndo, "no magic-number found!"));
  1066. return 0;
  1067. }
  1068. if (ndo->ndo_eflag) /* print direction */
  1069. ND_PRINT((ndo, "%3s ", tok2str(juniper_direction_values, "---", l2info->direction)));
  1070. /* magic number + flags */
  1071. jnx_header_len = 4;
  1072. if (ndo->ndo_vflag > 1)
  1073. ND_PRINT((ndo, "\n\tJuniper PCAP Flags [%s]",
  1074. bittok2str(jnx_flag_values, "none", l2info->flags)));
  1075. /* extensions present ? - calculate how much bytes to skip */
  1076. if ((l2info->flags & JUNIPER_BPF_EXT ) == JUNIPER_BPF_EXT ) {
  1077. tptr = p+jnx_header_len;
  1078. /* ok to read extension length ? */
  1079. ND_TCHECK2(tptr[0], 2);
  1080. jnx_ext_len = EXTRACT_16BITS(tptr);
  1081. jnx_header_len += 2;
  1082. tptr +=2;
  1083. /* nail up the total length -
  1084. * just in case something goes wrong
  1085. * with TLV parsing */
  1086. jnx_header_len += jnx_ext_len;
  1087. if (ndo->ndo_vflag > 1)
  1088. ND_PRINT((ndo, ", PCAP Extension(s) total length %u", jnx_ext_len));
  1089. ND_TCHECK2(tptr[0], jnx_ext_len);
  1090. while (jnx_ext_len > JUNIPER_EXT_TLV_OVERHEAD) {
  1091. tlv_type = *(tptr++);
  1092. tlv_len = *(tptr++);
  1093. tlv_value = 0;
  1094. /* sanity checks */
  1095. if (tlv_type == 0 || tlv_len == 0)
  1096. break;
  1097. if (tlv_len+JUNIPER_EXT_TLV_OVERHEAD > jnx_ext_len)
  1098. goto trunc;
  1099. if (ndo->ndo_vflag > 1)
  1100. ND_PRINT((ndo, "\n\t %s Extension TLV #%u, length %u, value ",
  1101. tok2str(jnx_ext_tlv_values,"Unknown",tlv_type),
  1102. tlv_type,
  1103. tlv_len));
  1104. tlv_value = juniper_read_tlv_value(tptr, tlv_type, tlv_len);
  1105. switch (tlv_type) {
  1106. case JUNIPER_EXT_TLV_IFD_NAME:
  1107. /* FIXME */
  1108. break;
  1109. case JUNIPER_EXT_TLV_IFD_MEDIATYPE:
  1110. case JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE:
  1111. if (tlv_value != -1) {
  1112. if (ndo->ndo_vflag > 1)
  1113. ND_PRINT((ndo, "%s (%u)",
  1114. tok2str(juniper_ifmt_values, "Unknown", tlv_value),
  1115. tlv_value));
  1116. }
  1117. break;
  1118. case JUNIPER_EXT_TLV_IFL_ENCAPS:
  1119. case JUNIPER_EXT_TLV_TTP_IFL_ENCAPS:
  1120. if (tlv_value != -1) {
  1121. if (ndo->ndo_vflag > 1)
  1122. ND_PRINT((ndo, "%s (%u)",
  1123. tok2str(juniper_ifle_values, "Unknown", tlv_value),
  1124. tlv_value));
  1125. }
  1126. break;
  1127. case JUNIPER_EXT_TLV_IFL_IDX: /* fall through */
  1128. case JUNIPER_EXT_TLV_IFL_UNIT:
  1129. case JUNIPER_EXT_TLV_IFD_IDX:
  1130. default:
  1131. if (tlv_value != -1) {
  1132. if (ndo->ndo_vflag > 1)
  1133. ND_PRINT((ndo, "%u", tlv_value));
  1134. }
  1135. break;
  1136. }
  1137. tptr+=tlv_len;
  1138. jnx_ext_len -= tlv_len+JUNIPER_EXT_TLV_OVERHEAD;
  1139. }
  1140. if (ndo->ndo_vflag > 1)
  1141. ND_PRINT((ndo, "\n\t-----original packet-----\n\t"));
  1142. }
  1143. if ((l2info->flags & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
  1144. if (ndo->ndo_eflag)
  1145. ND_PRINT((ndo, "no-L2-hdr, "));
  1146. /* there is no link-layer present -
  1147. * perform the v4/v6 heuristics
  1148. * to figure out what it is
  1149. */
  1150. ND_TCHECK2(p[jnx_header_len + 4], 1);
  1151. if (ip_heuristic_guess(ndo, p + jnx_header_len + 4,
  1152. l2info->length - (jnx_header_len + 4)) == 0)
  1153. ND_PRINT((ndo, "no IP-hdr found!"));
  1154. l2info->header_len=jnx_header_len+4;
  1155. return 0; /* stop parsing the output further */
  1156. }
  1157. l2info->header_len = jnx_header_len;
  1158. p+=l2info->header_len;
  1159. l2info->length -= l2info->header_len;
  1160. l2info->caplen -= l2info->header_len;
  1161. /* search through the cookie table and copy values matching for our PIC type */
  1162. ND_TCHECK(p[0]);
  1163. while (lp->s != NULL) {
  1164. if (lp->pictype == l2info->pictype) {
  1165. l2info->cookie_len += lp->cookie_len;
  1166. switch (p[0]) {
  1167. case LS_COOKIE_ID:
  1168. l2info->cookie_type = LS_COOKIE_ID;
  1169. l2info->cookie_len += 2;
  1170. break;
  1171. case AS_COOKIE_ID:
  1172. l2info->cookie_type = AS_COOKIE_ID;
  1173. l2info->cookie_len = 8;
  1174. break;
  1175. default:
  1176. l2info->bundle = l2info->cookie[0];
  1177. break;
  1178. }
  1179. #ifdef DLT_JUNIPER_MFR
  1180. /* MFR child links don't carry cookies */
  1181. if (l2info->pictype == DLT_JUNIPER_MFR &&
  1182. (p[0] & MFR_BE_MASK) == MFR_BE_MASK) {
  1183. l2info->cookie_len = 0;
  1184. }
  1185. #endif
  1186. l2info->header_len += l2info->cookie_len;
  1187. l2info->length -= l2info->cookie_len;
  1188. l2info->caplen -= l2info->cookie_len;
  1189. if (ndo->ndo_eflag)
  1190. ND_PRINT((ndo, "%s-PIC, cookie-len %u",
  1191. lp->s,
  1192. l2info->cookie_len));
  1193. if (l2info->cookie_len > 0) {
  1194. ND_TCHECK2(p[0], l2info->cookie_len);
  1195. if (ndo->ndo_eflag)
  1196. ND_PRINT((ndo, ", cookie 0x"));
  1197. for (idx = 0; idx < l2info->cookie_len; idx++) {
  1198. l2info->cookie[idx] = p[idx]; /* copy cookie data */
  1199. if (ndo->ndo_eflag) ND_PRINT((ndo, "%02x", p[idx]));
  1200. }
  1201. }
  1202. if (ndo->ndo_eflag) ND_PRINT((ndo, ": ")); /* print demarc b/w L2/L3*/
  1203. ND_TCHECK_16BITS(p+l2info->cookie_len);
  1204. l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len);
  1205. break;
  1206. }
  1207. ++lp;
  1208. }
  1209. p+=l2info->cookie_len;
  1210. /* DLT_ specific parsing */
  1211. switch(l2info->pictype) {
  1212. #ifdef DLT_JUNIPER_MLPPP
  1213. case DLT_JUNIPER_MLPPP:
  1214. switch (l2info->cookie_type) {
  1215. case LS_COOKIE_ID:
  1216. l2info->bundle = l2info->cookie[1];
  1217. break;
  1218. case AS_COOKIE_ID:
  1219. l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
  1220. l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
  1221. break;
  1222. default:
  1223. l2info->bundle = l2info->cookie[0];
  1224. break;
  1225. }
  1226. break;
  1227. #endif
  1228. #ifdef DLT_JUNIPER_MLFR
  1229. case DLT_JUNIPER_MLFR:
  1230. switch (l2info->cookie_type) {
  1231. case LS_COOKIE_ID:
  1232. ND_TCHECK2(p[0], 2);
  1233. l2info->bundle = l2info->cookie[1];
  1234. l2info->proto = EXTRACT_16BITS(p);
  1235. l2info->header_len += 2;
  1236. l2info->length -= 2;
  1237. l2info->caplen -= 2;
  1238. break;
  1239. case AS_COOKIE_ID:
  1240. l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
  1241. l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
  1242. break;
  1243. default:
  1244. l2info->bundle = l2info->cookie[0];
  1245. l2info->header_len += 2;
  1246. l2info->length -= 2;
  1247. l2info->caplen -= 2;
  1248. break;
  1249. }
  1250. break;
  1251. #endif
  1252. #ifdef DLT_JUNIPER_MFR
  1253. case DLT_JUNIPER_MFR:
  1254. switch (l2info->cookie_type) {
  1255. case LS_COOKIE_ID:
  1256. ND_TCHECK2(p[0], 2);
  1257. l2info->bundle = l2info->cookie[1];
  1258. l2info->proto = EXTRACT_16BITS(p);
  1259. l2info->header_len += 2;
  1260. l2info->length -= 2;
  1261. l2info->caplen -= 2;
  1262. break;
  1263. case AS_COOKIE_ID:
  1264. l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
  1265. l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
  1266. break;
  1267. default:
  1268. l2info->bundle = l2info->cookie[0];
  1269. break;
  1270. }
  1271. break;
  1272. #endif
  1273. #ifdef DLT_JUNIPER_ATM2
  1274. case DLT_JUNIPER_ATM2:
  1275. ND_TCHECK2(p[0], 4);
  1276. /* ATM cell relay control word present ? */
  1277. if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK) {
  1278. control_word = EXTRACT_32BITS(p);
  1279. /* some control word heuristics */
  1280. switch(control_word) {
  1281. case 0: /* zero control word */
  1282. case 0x08000000: /* < JUNOS 7.4 control-word */
  1283. case 0x08380000: /* cntl word plus cell length (56) >= JUNOS 7.4*/
  1284. l2info->header_len += 4;
  1285. break;
  1286. default:
  1287. break;
  1288. }
  1289. if (ndo->ndo_eflag)
  1290. ND_PRINT((ndo, "control-word 0x%08x ", control_word));
  1291. }
  1292. break;
  1293. #endif
  1294. #ifdef DLT_JUNIPER_GGSN
  1295. case DLT_JUNIPER_GGSN:
  1296. break;
  1297. #endif
  1298. #ifdef DLT_JUNIPER_ATM1
  1299. case DLT_JUNIPER_ATM1:
  1300. break;
  1301. #endif
  1302. #ifdef DLT_JUNIPER_PPP
  1303. case DLT_JUNIPER_PPP:
  1304. break;
  1305. #endif
  1306. #ifdef DLT_JUNIPER_CHDLC
  1307. case DLT_JUNIPER_CHDLC:
  1308. break;
  1309. #endif
  1310. #ifdef DLT_JUNIPER_ETHER
  1311. case DLT_JUNIPER_ETHER:
  1312. break;
  1313. #endif
  1314. #ifdef DLT_JUNIPER_FRELAY
  1315. case DLT_JUNIPER_FRELAY:
  1316. break;
  1317. #endif
  1318. default:
  1319. ND_PRINT((ndo, "Unknown Juniper DLT_ type %u: ", l2info->pictype));
  1320. break;
  1321. }
  1322. if (ndo->ndo_eflag > 1)
  1323. ND_PRINT((ndo, "hlen %u, proto 0x%04x, ", l2info->header_len, l2info->proto));
  1324. return 1; /* everything went ok so far. continue parsing */
  1325. trunc:
  1326. ND_PRINT((ndo, "[|juniper_hdr], length %u", h->len));
  1327. return 0;
  1328. }
  1329. /*
  1330. * Local Variables:
  1331. * c-style: whitesmith
  1332. * c-basic-offset: 4
  1333. * End:
  1334. */