ofs | hex dump | ascii |
---|
0000 | 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 09 34 00 00 06 be 08 06 00 00 00 62 ce 27 | .PNG........IHDR...4.........b.' |
0020 | ea 00 00 0c 24 69 43 43 50 49 43 43 20 50 72 6f 66 69 6c 65 00 00 48 89 95 57 07 54 93 c9 16 9e | ....$iCCPICC.Profile..H..W.T.... |
0040 | bf 24 21 21 a1 05 22 20 25 f4 26 4a 91 2e bd 46 10 90 2a d8 08 49 20 a1 c4 98 10 54 ec e8 a2 02 | .$!!..".%.&J...F..*..I.....T.... |
0060 | 6b 41 45 04 2b ba 2a a2 e8 8a 14 59 6c d8 50 59 14 7b 5f 14 51 51 d6 c5 82 0d 35 6f 92 00 ba ee | kAE.+.*....Yl.PY.{_.QQ....5o.... |
0080 | 2b e7 dd 73 e6 9f ef bf 73 ef 9d ef 4e 3b 33 00 a8 47 b3 45 a2 2c 54 03 80 6c 61 8e 38 26 34 80 | +..s....s...N;3..G.E.,T..la.8&4. |
00a0 | 39 29 29 99 49 7a 04 10 c0 00 24 60 05 54 d9 1c 89 c8 3f 3a 3a 02 40 19 aa ff 2e ef 6e 40 6b 28 | 9)).Iz....$`.T....?::.@.....n@k( |
00c0 | 57 ed e5 b1 fe d9 fe 5f 45 93 cb 93 70 00 40 a2 21 4e e5 4a 38 d9 10 1f 06 00 77 e5 88 c4 39 00 | W......_E...p.@.!N.J8.....w...9. |
00e0 | 10 7a a1 de 6c 56 8e 08 62 22 64 09 b4 c5 90 20 c4 e6 72 9c ae c4 ee 72 9c aa c4 11 0a 9b b8 98 | .z..lV..b"d.......r....r........ |
0100 | 40 88 53 00 50 a1 b2 d9 e2 74 00 d4 e4 bc 98 b9 9c 74 18 47 ad 18 62 07 21 57 20 84 b8 19 62 1f | @.S.P....t.......t.G..b.!W....b. |
0120 | 0e 9f cd 85 f8 33 c4 a3 b2 b3 67 40 ac 6e 0d b1 75 ea 77 71 d2 ff 16 33 75 38 26 9b 9d 3e 8c 95 | .....3....g@.n..u.wq...3u8&..>.. |
0140 | b9 28 44 25 48 20 11 65 b1 e7 fc 9f c3 f1 bf 25 3b 4b 3a d4 87 19 2c 54 be 38 2c 46 9e b3 7c dc | .(D%H..e.......%;K:...,T.8,F..|. |
0160 | 32 67 84 cb 31 15 e2 56 61 6a 64 14 c4 5a 10 5f 13 70 15 f6 72 fc 84 2f 0d 8b 1f b4 ff c0 91 04 | 2g..1..Vajd..Z._.p..r../........ |
0180 | c2 31 83 33 0d 50 2a 97 1d 14 0e b1 01 c4 a6 d2 cc 78 ff 41 ec c3 16 2b 7c a1 3d 9a 9c c7 8f 4b | .1.3.P*..........x.A...+|.=....K |
01a0 | 54 c6 47 85 e2 19 31 83 f1 d1 3c 61 56 64 c4 60 9c 62 3e 8f 35 84 2b 79 92 e0 d8 21 9b 34 41 08 | T.G...1...<aVd.`.b>.5.+y...!.4A. |
01c0 | 0b 62 38 87 68 a3 20 87 15 37 18 b3 35 57 90 10 09 b1 1a c4 f7 24 99 b1 e1 83 be cf f3 f8 81 91 | .b8.h....7..5W.......$.......... |
01e0 | c3 7d 49 63 e4 9c e1 9c 63 20 5b 32 94 0b 66 9e 26 0e 89 51 da 63 ae 7c 01 2b 72 50 1f 91 c3 8f | .}Ic....c.[2..f.&..Q.c.|.+rP.... |
0200 | 0b 53 fa 62 d3 38 6c 05 07 5d 88 33 78 92 49 11 43 7c b8 bc a0 60 25 1f 2c 9f 27 8c 1f e4 89 95 | .S.b.8l..].3x.I.C|...`%.,.'..... |
0220 | 88 72 02 62 06 ed 77 8a b2 a2 07 ed b1 66 5e 56 a8 5c 6f 0a 71 bb 24 37 76 c8 b7 2f 07 2e 36 65 | .r.b..w......f^V.\o.q.$7v../..6e |
0240 | 2e 38 c8 60 8f 8f 56 f6 8b 6b 8b 72 a2 e3 94 dc 70 26 88 00 81 20 08 30 81 14 96 54 30 03 64 00 | .8.`..V..k.r....p&.....0...T0.d. |
0260 | 41 7b 6f 43 2f 18 6a 09 01 6c 20 06 e9 80 07 ec 07 35 43 1e 89 8a 16 21 fc c6 82 3c f0 27 44 3c | A{oC/.j..l.......5C....!...<.'D< |
0280 | 20 19 f6 0b 50 b4 f2 40 2e d4 7f 19 d6 2a bf f6 20 4d d1 9a ab f0 c8 04 4f 20 ce c6 f5 71 1f dc | ....P..@.....*...M......O....q.. |
02a0 | 0b 8f 80 5f 3f 58 9c 70 77 dc 63 c8 8f a9 3e d4 2b 31 98 18 44 0c 23 86 10 6d a6 0b f2 c5 3f c4 | ..._?X.pw.c...>.+1..D.#..m....?. |
02c0 | 65 02 0e cc 20 0b 16 31 08 87 35 0f 66 25 e7 20 1c e2 fe 2d 0e e1 09 a1 83 f0 88 70 9d d0 49 b8 | e......1..5.f%.....-.......p..I. |
02e0 | 0d 12 c0 63 68 27 f8 47 86 df a2 09 86 75 13 40 27 8c 1a 32 98 5d ea f7 d9 e1 96 90 b5 0b 1e 80 | ...ch'.G.....u.@'..2.].......... |
0300 | 7b 43 fe 90 3b ce c0 f5 81 3d 3e 16 66 e2 8f fb c2 dc 5c a0 f6 db a8 fd 3b ee d2 21 d6 64 07 32 | {C..;....=>.f.....\.....;..!.d.2 |
0320 | 4a 1e 41 f6 23 5b ff 68 a7 66 ab e6 32 ec 23 cf ed 7b 9e 4a 5e a9 c3 99 04 0e b7 fc d8 5b e0 77 | J.A.#[.h.f..2.#..{.J^........[.w |
0340 | b9 71 61 1d fe a3 25 b6 1c ab c5 ce 61 27 b1 f3 58 33 d6 00 98 d8 71 ac 11 6b c3 8e ca f1 f0 da | .qa...%.....a'..X3....q..k...... |
0360 | 78 ac 58 1b 43 bd c5 28 f8 64 c2 38 82 21 1b 87 6a 87 1e 87 cf 3f f4 cd 1e ec 5f ac 98 7f 90 c3 | x.X.C..(.d.8.!..j....?...._..... |
0380 | 9b 9d 23 df 38 81 33 44 73 c4 82 74 7e 0e d3 1f 9e d6 3c 26 4b c8 19 3d 8a e9 e4 e0 08 4f 51 f9 | ..#.8.3Ds..t~.....<&K..=.....OQ. |
03a0 | d9 af 3c 5a de 30 14 67 3a c2 b8 f0 4d 57 d0 05 80 ef 38 99 4c d6 f4 4d 17 b6 1b 80 5a 55 00 28 | ..<Z.0.g:...MW....8.L..M....ZU.( |
03c0 | c7 be e9 ac e0 9e a1 1d 01 a0 b5 8e 23 15 e7 2a 75 b8 fc 43 00 14 a0 0e 77 8a 1e 30 82 67 97 35 | ............#..*u..C....w..0.g.5 |
03e0 | cc c8 09 b8 02 2f e0 07 82 c1 78 10 05 e2 40 12 98 06 c7 99 0f b2 21 eb 59 60 1e 58 0c 0a 40 11 | ...../....x...@.......!.Y`.X..@. |
0400 | 58 0d d6 83 72 b0 15 ec 00 7b c0 7e 70 08 34 80 66 70 12 9c 05 17 c1 65 70 1d dc 85 6b a5 1b bc | X...r....{.~p.4.fp.....ep...k... |
0420 | 00 7d e0 1d 18 40 10 84 84 d0 10 3a a2 87 18 23 16 88 1d e2 84 b8 23 3e 48 30 12 81 c4 20 49 48 | .}...@.....:...#......#>H0....IH |
0440 | 0a 92 8e 08 11 29 32 0f 59 82 14 21 25 48 39 b2 1d a9 42 7e 45 8e 20 27 91 f3 48 07 72 1b 79 88 | .....)2.Y..!%H9...B~E..'..H.r.y. |
0460 | f4 20 af 91 4f 28 86 52 51 6d d4 10 b5 44 c7 a0 ee a8 3f 1a 8e c6 a1 53 d1 74 74 26 9a 87 2e 45 | ....O(.RQm...D....?....S.tt&...E |
0480 | 57 a2 65 68 25 ba 0f ad 47 4f a2 17 d1 eb 68 27 fa 02 ed c7 00 a6 8a 31 30 13 cc 1e 73 c7 02 b1 | W.eh%...GO....h'.......10...s... |
04a0 | 28 2c 19 4b c3 c4 d8 02 ac 10 2b c5 2a b1 1a ac 09 ce f4 55 ac 13 eb c5 3e e2 44 9c 8e 33 71 7b | (,.K......+.*......U....>.D..3q{ |
04c0 | b8 5e c3 f0 78 9c 83 cf c4 17 e0 c5 78 39 be 07 af c7 4f e3 57 f1 87 78 1f fe 95 40 23 18 10 ec | .^..x.......x9....O.W..x...@#... |
04e0 | 08 9e 04 16 61 12 21 9d 30 8b 50 40 28 25 ec 22 d4 11 ce c0 3d d5 4d 78 47 24 12 19 44 2b a2 1b | ....a.!.0.P@(%."....=.MxG$..D+.. |
0500 | dc ab 49 c4 0c e2 5c 62 31 71 33 f1 00 f1 04 b1 83 d8 45 ec 27 91 48 7a 24 3b 92 37 29 8a c4 26 | ..I...\b1q3.......E.'.Hz$;.7)..& |
0520 | e5 90 0a 48 1b 49 fb 48 c7 49 57 48 dd a4 0f 2a aa 2a c6 2a 4e 2a 21 2a c9 2a 42 95 7c 95 52 95 | ...H.I.H.IWH...*.*.*N*!*.*B.|.R. |
0540 | bd 2a c7 54 ae a8 3c 55 19 20 6b 90 2d c8 9e e4 28 32 97 3c 87 bc 8a bc 93 dc 44 be 44 ee 26 0f | .*.T..<U..k.-...(2.<......D.D.&. |
0560 | 50 34 29 56 14 6f 4a 1c 25 83 b2 98 52 46 a9 a1 9c a1 dc a3 bc 51 55 55 35 55 f5 50 9d a8 2a 50 | P4)V.oJ.%...RF.......QUU5U.P..*P |
0580 | 5d a4 5a a6 7a 50 b5 55 f5 a1 ea 47 aa 16 d5 96 1a 48 9d 42 95 52 57 52 77 53 4f 50 6f 53 df d0 | ].Z.zP.U...G.....H.B.RWRwSOPoS.. |
05a0 | 68 34 4b 9a 1f 2d 99 96 43 5b 49 ab a2 9d a2 3d a0 7d 50 a3 ab 8d 56 63 a9 71 d5 16 aa 55 a8 d5 | h4K..-..C[I....=.}P...Vc.q...U.. |
05c0 | ab 5d 51 7b a9 4e 56 b7 50 f7 57 9f a6 9e a7 5e aa 5e ab 7e 49 bd 57 83 ac 61 a9 11 a8 c1 d6 58 | .]Q{.NV.P.W....^.^.~I.W..a.....X |
05e0 | a0 51 a1 71 44 e3 a6 46 bf 26 5d d3 51 33 4a 33 5b b3 58 73 af e6 79 cd 67 5a 24 2d 4b ad 60 2d | .Q.qD..F.&].Q3J3[.Xs..y.gZ$-K.`- |
0600 | ae d6 52 ad 1d 5a a7 b4 ba e8 18 dd 8c 1e 48 e7 d0 97 d0 77 d2 cf d0 bb b5 89 da 56 da 2c ed 0c | ..R..Z........H....w.......V.,.. |
0620 | ed 22 ed fd da ed da 7d 3a 5a 3a 63 75 12 74 66 eb 54 e8 1c d5 e9 64 60 0c 4b 06 8b 91 c5 58 c5 | .".....}:Z:cu.tf.T....d`.K....X. |
0640 | 38 c4 b8 c1 f8 34 c2 70 84 ff 08 de 88 15 23 6a 46 5c 19 f1 5e 77 a4 ae 9f 2e 4f b7 50 f7 80 ee | 8....4.p......#jF\..^w....O.P... |
0660 | 75 dd 4f 7a 4c bd 60 bd 4c bd 35 7a 0d 7a f7 f5 71 7d 5b fd 89 fa b3 f4 b7 e8 9f d1 ef 1d a9 3d | u.OzL.`.L.5z.z..q}[............= |
0680 | d2 6b 24 67 64 e1 c8 43 23 ef 18 a0 06 b6 06 31 06 73 0d 76 18 b4 19 f4 1b 1a 19 86 1a 8a 0c 37 | .k$gd..C#......1.s.v...........7 |
06a0 | 1a 9e 32 ec 35 62 18 f9 19 65 18 ad 33 3a 66 d4 63 4c 37 f6 31 16 18 af 33 3e 6e fc 9c a9 c3 f4 | ..2.5b...e..3:f.cL7.1...3>n..... |
06c0 | 67 66 31 cb 98 a7 99 7d 26 06 26 61 26 52 93 ed 26 ed 26 03 a6 56 a6 f1 a6 f9 a6 07 4c ef 9b 51 | gf1....}&.&a&R..&.&..V......L..Q |
06e0 | cc dc cd d2 cc d6 99 b5 98 f5 99 1b 9b 4f 30 9f 67 5e 6d 7e c7 82 6c e1 6e c1 b7 d8 60 71 ce e2 | .............O0.g^m~..l.n...`q.. |
0700 | bd a5 95 65 a2 e5 32 cb 06 cb 67 56 ba 56 2c ab 3c ab 6a ab 7b d6 34 6b 5f eb 99 d6 95 d6 d7 6c | ...e..2...gV.V,.<.j.{.4k_......l |
0720 | 88 36 ee 36 99 36 9b 6d 2e db a2 b6 2e b6 7c db 0a db 4b 76 a8 9d ab 9d c0 6e b3 5d c7 28 c2 28 | .6.6.6.m......|...Kv.....n.].(.( |
0740 | 8f 51 c2 51 95 a3 6e da 53 ed fd ed 73 ed ab ed 1f 8e 66 8c 8e 18 9d 3f ba 61 f4 cb 31 e6 63 92 | .Q.Q..n.S...s.....f....?.a..1.c. |
0760 | c7 ac 19 73 6e cc 57 07 17 87 2c 87 9d 0e 77 1d b5 1c c7 3b e6 3b 36 39 be 76 b2 75 e2 38 55 38 | ...sn.W...,...w....;.;69.v.u.8U8 |
0780 | 5d 73 a6 39 87 38 2f 74 6e 74 7e 35 d6 6e 2c 6f ec 96 b1 b7 5c e8 2e 13 5c 96 b9 b4 b8 7c 71 75 | ]s.9.8/tnt~5.n,o....\...\....|qu |
07a0 | 73 15 bb d6 b8 f6 b8 99 bb a5 b8 6d 72 bb e9 ae ed 1e ed 5e ec de ea 41 f0 08 f0 58 e8 d1 ec f1 | s..........mr......^...A...X.... |
07c0 | d1 d3 d5 33 c7 f3 90 e7 5f 5e f6 5e 99 5e 7b bd 9e 8d b3 1a c7 1b b7 73 5c 97 b7 a9 37 db 7b bb | ...3...._^.^.^{........s\...7.{. |
07e0 | 77 a7 0f d3 27 c5 67 9b 4f a7 af 89 2f db b7 d2 f7 91 9f 99 1f d7 6f 97 df 53 7f 1b ff 0c ff 7d | w...'.g.O.../.........o..S.....} |
0800 | fe 2f 03 1c 02 c4 01 75 01 ef 03 3d 03 e7 07 9e 08 c2 82 42 83 0a 83 da 83 b5 82 e3 83 cb 83 1f | ./.....u...=.......B............ |
0820 | 84 98 86 a4 87 54 87 f4 85 ba 84 ce 0d 3d 11 46 08 0b 0f 5b 13 76 93 65 c8 e2 b0 aa 58 7d e3 dd | .....T.......=.F...[.v.e....X}.. |
0840 | c6 cf 1f 7f 3a 9c 1a 1e 1b 5e 1e fe 28 c2 36 42 1c d1 34 01 9d 30 7e c2 da 09 f7 22 2d 22 85 91 | ....:....^..(.6B..4..0~...."-".. |
0860 | 0d 51 20 8a 15 b5 36 ea 7e b4 55 f4 cc e8 df 26 12 27 46 4f ac 98 f8 24 c6 31 66 5e cc b9 58 7a | .Q....6.~.U....&.'FO...$.1f^..Xz |
0880 | ec f4 d8 bd b1 ef e2 02 e2 56 c5 dd 8d b7 8e 97 c6 b7 24 a8 27 4c 49 a8 4a 78 9f 18 94 58 92 d8 | .........V........$.'LI.Jx...X.. |
08a0 | 39 69 cc a4 f9 93 2e 26 e9 27 09 92 1a 93 49 c9 09 c9 bb 92 fb 27 07 4f 5e 3f b9 7b 8a cb 94 82 | 9i.....&.'....I......'.O^?.{.... |
08c0 | 29 37 a6 5a 4d 9d 3d f5 fc 34 fd 69 59 d3 8e 4e 57 9f ce 9e 5e 9b 42 48 49 4c d9 9b f2 99 1d c5 | )7.ZM.=..4.iY..NW...^.BHIL...... |
08e0 | ae 64 f7 a7 b2 52 37 a5 f6 71 02 39 1b 38 2f b8 7e dc 75 dc 1e 9e 37 af 84 f7 34 cd 3b ad 24 ed | .d...R7..q.9.8/.~.u...7...4.;.$. |
0900 | 59 ba 77 fa da f4 1e be 2f bf 94 df 2b 08 14 94 0b 5e 65 84 65 6c cd 78 9f 19 95 b9 3b 53 96 95 | Y.w...../...+....^e.el.x....;S.. |
0920 | 98 75 20 5b 25 3b 25 fb 88 50 4b 98 29 3c 3d c3 68 c6 ec 19 1d 22 3b 51 81 a8 73 a6 e7 cc f5 33 | .u.[%;%..PK.)<=.h....";Q..s....3 |
0940 | fb c4 e1 e2 5d 12 44 32 55 d2 98 a3 0d 2f d9 6d 52 6b e9 4f d2 87 b9 3e b9 15 b9 1f 66 25 cc aa | ....].D2U..../.mRk.O...>....f%.. |
0960 | 9d ad 39 5b 38 bb 6d 8e ed 9c 15 73 9e e6 85 e4 fd 32 17 9f cb 99 db 32 cf 64 de e2 79 0f e7 fb | ..9[8.m....s.....2.....2.d..y... |
0980 | cf df be 00 59 90 ba a0 65 a1 d9 c2 a5 0b bb 17 85 2e da b3 98 b2 38 73 f1 ef f9 0e f9 25 f9 6f | ....Y...e.............8s.....%.o |
09a0 | 97 24 2e 69 5a 6a b8 74 d1 d2 ae 9f 42 7f aa 2e 50 2b 10 17 dc 5c e6 b5 6c eb 72 7c b9 60 79 fb | .$.iZj.t....B...P+...\..l.r|.`y. |
09c0 | 0a e7 15 1b 57 7c 2d e4 16 5e 28 72 28 2a 2d fa 5c cc 29 be f0 b3 e3 cf 65 3f cb 56 a6 ad 6c 5f | ....W|-..^(r(*-.\.).....e?.V..l_ |
09e0 | e5 ba 6a cb 6a e2 6a e1 ea 1b 6b 7c d7 ec 29 d1 2c c9 2b e9 5a 3b 61 6d fd 3a e6 ba c2 75 6f d7 | ..j.j.j...k|..).,.+.Z;am.:...uo. |
0a00 | 4f 5f 7f be 74 6c e9 d6 0d 94 0d d2 0d 9d 65 11 65 8d 1b cd 37 ae de f8 b9 9c 5f 7e bd 22 a0 e2 | O_..tl........e.e...7....._~.".. |
0a20 | c0 26 83 4d 2b 36 bd df cc dd 7c 65 8b df 96 9a ad 86 5b 8b b6 7e da 26 d8 76 6b 7b e8 f6 fa 4a | .&.M+6....|e......[..~.&.vk{...J |
0a40 | cb ca d2 1d c4 1d b9 3b 9e ec 4c d8 79 ee 17 f7 5f aa 76 e9 ef 2a da f5 65 b7 70 77 e7 9e 98 3d | .......;..L.y..._.v..*..e.pw...= |
0a60 | a7 ab dc aa aa f6 1a ec 5d 55 8d 56 4b ab 7b f6 4d d9 77 79 7f d0 fe c6 1a fb 9a ed 07 18 07 8a | ........]U.VK.{.M.wy............ |
0a80 | 0e 82 83 d2 83 cf 7f 4d f9 f5 c6 a1 f0 43 2d b5 ee b5 35 87 2d 0e 6f aa a3 d7 15 d6 23 f5 73 ea | .......M.....C-...5.-.o.....#.s. |
0aa0 | fb 1a f8 0d 9d 8d 49 8d 1d 47 c6 1f 69 69 f2 6a aa fb 6d f4 6f bb 9b 4d 9a 2b 8e ea 1c 5d 75 8c | ......I..G..ii.j..m.o..M.+...]u. |
0ac0 | 72 6c e9 31 d9 f1 bc e3 fd 27 44 27 7a 4f a6 9f ec 6a 99 de 72 f7 d4 a4 53 d7 4e 4f 3c dd 7e 26 | rl.1.....'D'zO...j..r...S.NO<.~& |
0ae0 | fc 4c eb d9 90 b3 a7 ce f9 9f 3b de ea dd da 7c de f3 fc 91 0b ee 17 1a 2e ba 5e ac 6f 73 69 ab | .L........;....|..........^.osi. |
0b00 | fb dd e5 f7 ba 76 d7 f6 fa 4b 6e 97 1a 2f 7b 5c 6e ea 18 d7 71 ec 8a ef 95 93 57 83 ae 9e bd c6 | .....v...Kn../{\n...q.....W..... |
0b20 | ba 76 f1 7a e4 f5 8e 1b f1 37 6e dd 9c 72 b3 f3 16 f7 d6 b3 db 59 b7 5f dd c9 bd 33 70 77 d1 3d | .v.z.....7n..r.......Y._...3pw.= |
0b40 | c2 bd c2 fb 1a f7 4b 1f 18 3c a8 fc c3 e6 8f 03 9d ae 9d 47 1f 06 3d 6c 7b 14 fb e8 6e 17 a7 eb | ......K..<.........G..=l{...n... |
0b60 | c5 63 c9 e3 cf dd 4b 9f d0 9e 94 3e 35 7e 5a f5 cc e9 59 73 4f 48 cf e5 e7 93 9f 77 bf 10 bd 18 | .c....K....>5~Z...YsOH.....w.... |
0b80 | e8 2d f8 53 f3 cf 4d 2f ad 5f 1e fe cb ef af b6 be 49 7d dd af c4 af 64 af 8b df e8 bd d9 fd 76 | .-.S..M/._.......I}....d.......v |
0ba0 | ec db 96 fe e8 fe 07 ef b2 df 0d bc 2f fc a0 f7 61 cf 47 f7 8f e7 3e 25 7e 7a 3a 30 eb 33 e9 73 | ............/...a.G...>%~z:0.3.s |
0bc0 | d9 17 9b 2f 4d 5f c3 bf de 93 65 cb 64 22 b6 98 ad b8 0a 60 b0 a0 69 69 00 bc 86 77 07 5a 12 00 | .../M_....e.d".....`..ii...w.Z.. |
0be0 | f4 cb f0 fe 30 59 f9 36 53 08 a2 7c 4f 2a 10 f8 4f 58 f9 7e 53 88 2b 00 35 b0 92 5f c3 fd 4f 00 | ....0Y.6S..|O*..OX.~S.+.5.._..O. |
0c00 | 70 08 16 4b 3f 18 1b fe cb af e3 71 7e 00 75 76 1e 2e 83 22 49 73 76 52 c6 a2 c2 17 0e e1 83 4c | p..K?......q~.uv..."IsvR.......L |
0c20 | f6 c6 10 00 52 13 00 5f c4 32 d9 c0 66 99 ec cb 4e 48 f6 36 00 27 66 2a df 84 72 91 bf 41 b7 39 | ....R.._.2..f...NH.6.'f*..r..A.9 |
0c40 | c8 d1 15 e3 5a f0 a3 fc 0b 5d 3d 70 24 56 26 19 e3 00 00 00 09 70 48 59 73 00 00 16 25 00 00 16 | ....Z....]=p$V&......pHYs...%... |
0c60 | 25 01 49 52 24 f0 00 00 02 06 69 54 58 74 58 4d 4c 3a 63 6f 6d 2e 61 64 6f 62 65 2e 78 6d 70 00 | %.IR$.....iTXtXML:com.adobe.xmp. |
0c80 | 00 00 00 00 3c 78 3a 78 6d 70 6d 65 74 61 20 78 6d 6c 6e 73 3a 78 3d 22 61 64 6f 62 65 3a 6e 73 | ....<x:xmpmeta.xmlns:x="adobe:ns |
0ca0 | 3a 6d 65 74 61 2f 22 20 78 3a 78 6d 70 74 6b 3d 22 58 4d 50 20 43 6f 72 65 20 35 2e 34 2e 30 22 | :meta/".x:xmptk="XMP.Core.5.4.0" |
0cc0 | 3e 0a 20 20 20 3c 72 64 66 3a 52 44 46 20 78 6d 6c 6e 73 3a 72 64 66 3d 22 68 74 74 70 3a 2f 2f | >....<rdf:RDF.xmlns:rdf="http:// |
0ce0 | 77 77 77 2e 77 33 2e 6f 72 67 2f 31 39 39 39 2f 30 32 2f 32 32 2d 72 64 66 2d 73 79 6e 74 61 78 | www.w3.org/1999/02/22-rdf-syntax |
0d00 | 2d 6e 73 23 22 3e 0a 20 20 20 20 20 20 3c 72 64 66 3a 44 65 73 63 72 69 70 74 69 6f 6e 20 72 64 | -ns#">.......<rdf:Description.rd |
0d20 | 66 3a 61 62 6f 75 74 3d 22 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 78 6d 6c 6e 73 3a 65 78 69 | f:about="".............xmlns:exi |
0d40 | 66 3d 22 68 74 74 70 3a 2f 2f 6e 73 2e 61 64 6f 62 65 2e 63 6f 6d 2f 65 78 69 66 2f 31 2e 30 2f | f="http://ns.adobe.com/exif/1.0/ |
0d60 | 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 78 6d 6c 6e 73 3a 74 69 66 66 3d 22 68 74 74 70 3a 2f | ".............xmlns:tiff="http:/ |
0d80 | 2f 6e 73 2e 61 64 6f 62 65 2e 63 6f 6d 2f 74 69 66 66 2f 31 2e 30 2f 22 3e 0a 20 20 20 20 20 20 | /ns.adobe.com/tiff/1.0/">....... |
0da0 | 20 20 20 3c 65 78 69 66 3a 50 69 78 65 6c 59 44 69 6d 65 6e 73 69 6f 6e 3e 31 37 32 36 3c 2f 65 | ...<exif:PixelYDimension>1726</e |
0dc0 | 78 69 66 3a 50 69 78 65 6c 59 44 69 6d 65 6e 73 69 6f 6e 3e 0a 20 20 20 20 20 20 20 20 20 3c 65 | xif:PixelYDimension>..........<e |
0de0 | 78 69 66 3a 50 69 78 65 6c 58 44 69 6d 65 6e 73 69 6f 6e 3e 32 33 35 36 3c 2f 65 78 69 66 3a 50 | xif:PixelXDimension>2356</exif:P |
0e00 | 69 78 65 6c 58 44 69 6d 65 6e 73 69 6f 6e 3e 0a 20 20 20 20 20 20 20 20 20 3c 74 69 66 66 3a 4f | ixelXDimension>..........<tiff:O |
0e20 | 72 69 65 6e 74 61 74 69 6f 6e 3e 31 3c 2f 74 69 66 66 3a 4f 72 69 65 6e 74 61 74 69 6f 6e 3e 0a | rientation>1</tiff:Orientation>. |
0e40 | 20 20 20 20 20 20 3c 2f 72 64 66 3a 44 65 73 63 72 69 70 74 69 6f 6e 3e 0a 20 20 20 3c 2f 72 64 | ......</rdf:Description>....</rd |
0e60 | 66 3a 52 44 46 3e 0a 3c 2f 78 3a 78 6d 70 6d 65 74 61 3e 0a 55 c6 d3 dd 00 00 40 00 49 44 41 54 | f:RDF>.</x:xmpmeta>.U.....@.IDAT |
0e80 | 78 01 ec dd 57 70 5c e7 7d c7 fd 3f 7a 23 1a 41 80 04 c0 de 29 52 a4 d8 29 52 14 45 51 14 65 59 | x...Wp\.}..?z#.A....)R..)R.EQ.eY |
0ea0 | b2 a4 58 b6 65 8f a3 b1 e3 71 92 8b 4c ca 5d ee f2 4e 26 17 b9 c9 cd 9b 32 9e 89 93 c9 eb 58 b1 | ..X.e....q..L.]..N&.....2.....X. |
0ec0 | a5 a8 5b 14 55 42 49 94 c4 26 f6 de 49 b0 80 e8 20 7a 2f ef f3 7b a8 03 2d 17 bb 28 24 40 2e a8 | ..[.UBI..&..I....z/..{..-..($@.. |
0ee0 | ef c9 2c 77 f7 ec 39 cf f3 9c cf d9 0c ec ec 2f ff 7f 5c af db 8c 0d 01 04 10 40 00 01 04 10 40 | ..,w..9......../..\.......@....@ |
0f00 | 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 | ....@....@....@....@....@....@.. |
0f20 | 04 10 88 01 81 f8 18 58 03 4b 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 | .......X.K@....@....@....@....@. |
0f40 | 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 bc 00 81 26 be 08 08 20 80 00 | ...@....@....@....@......&...... |
0f60 | 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 | ................................ |
0f80 | 20 80 00 02 08 20 10 33 02 04 9a 62 e6 56 b0 10 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 | .......3...b.V....@....@....@... |
0fa0 | 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 20 d0 c4 77 00 01 | .@....@....@....@....@.......w.. |
0fc0 | 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 | ..@....@....@....@....@....@.... |
0fe0 | 40 00 01 04 10 40 00 01 04 62 46 80 40 53 cc dc 0a 16 82 00 02 08 20 80 00 02 08 20 80 00 02 08 | @....@...bF.@S.................. |
1000 | 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 04 9a f8 | ................................ |
1020 | 0e 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 | ................................ |
1040 | 80 00 02 08 20 80 00 02 08 20 80 40 cc 08 10 68 8a 99 5b c1 42 10 40 00 01 04 10 40 00 01 04 10 | ...........@...h..[.B.@....@.... |
1060 | 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 80 | @....@....@....@....@....@....@. |
1080 | 40 13 df 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 | @.....@....@....@....@....@....@ |
10a0 | 00 01 04 10 40 00 01 04 10 40 00 01 04 10 88 19 01 02 4d 31 73 2b 58 08 02 08 20 80 00 02 08 20 | ....@....@........M1s+X......... |
10c0 | 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 | ................................ |
10e0 | 02 08 10 68 e2 3b 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 | ...h.;.......................... |
1100 | 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 31 23 40 a0 29 66 6e 05 0b 41 00 01 04 10 40 | .................1#@.)fn..A....@ |
1120 | 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 | ....@....@....@....@....@....@.. |
1140 | 04 10 40 00 01 02 4d 7c 07 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 | ..@...M|..@....@....@....@....@. |
1160 | 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 20 66 04 08 34 c5 cc ad 60 21 08 20 80 | ...@....@....@....@.f..4...`!... |
1180 | 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 | ................................ |
11a0 | 08 20 80 00 02 08 20 40 a0 89 ef 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 | .......@........................ |
11c0 | 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 c4 8c 00 81 a6 98 b9 15 2c 04 | ..............................,. |
11e0 | 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 | ...@....@....@....@....@....@... |
1200 | 10 40 00 01 04 10 40 00 01 04 08 34 f1 1d 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 | .@....@....4..@....@....@....@.. |
1220 | 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 81 98 11 20 d0 14 33 b7 | ..@....@....@....@....@.......3. |
1240 | 82 85 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 | ................................ |
1260 | 20 80 00 02 08 20 80 00 02 08 20 80 00 81 26 be 03 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 | ..............&................. |
1280 | 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 10 33 02 04 9a | ............................3... |
12a0 | 62 e6 56 b0 10 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 | b.V....@....@....@....@....@.... |
12c0 | 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 20 d0 c4 77 00 01 04 10 40 00 01 04 10 40 00 01 04 | @....@....@.......w....@....@... |
12e0 | 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 62 46 | .@....@....@....@....@....@...bF |
1300 | 80 40 53 cc dc 0a 16 82 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 | .@S............................. |
1320 | 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 04 9a f8 0e 20 80 00 02 08 20 80 00 02 08 | ................................ |
1340 | 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 | ................................ |
1360 | 40 cc 08 10 68 8a 99 5b c1 42 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 | @...h..[.B.@....@....@....@....@ |
1380 | 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 80 40 13 df 01 04 10 40 00 01 04 10 | ....@....@....@....@.@.....@.... |
13a0 | 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 | @....@....@....@....@....@....@. |
13c0 | 01 04 10 88 19 81 c4 98 59 09 0b 19 92 40 7b 67 b7 b5 b5 77 59 77 6f ef 90 8e 0f 3d 28 ce dc ff | ........Y....@{g...wYwo....=(... |
13e0 | c4 99 7b c4 59 62 bc 7b 24 c6 5b 92 7b c4 6b 27 1b 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 | ..{.Yb.{$.[.{.k'................ |
1400 | 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 31 20 40 a0 29 06 | ..........................1.@.). |
1420 | 6e c2 70 96 50 52 d6 60 c7 2e d6 58 53 4b c7 70 4e f3 c7 fa 20 53 c2 cd 10 53 7a 4a a2 65 8f 4b | n.p.PR.`...XSK.pN....S...SzJ.e.K |
1440 | b1 bc ec 54 f7 9c 6c 59 e9 c9 96 9e 9a 64 09 2e e8 c4 86 00 02 08 20 80 00 02 08 20 80 00 02 08 | ...T..lY.....d.................. |
1460 | 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 c0 bd 12 20 d0 | ................................ |
1480 | 74 af e4 6f 73 de 1b 8d ed 76 fc 42 b5 5d ae 68 b4 ce ae 9e db 1c e5 9b d3 92 93 12 6c 46 61 96 | t..os....v.B.].h............lFa. |
14a0 | 2d 9c 91 67 73 a6 e4 d8 e4 fc 71 96 95 91 4c b0 e9 1b 22 5e 21 80 00 02 08 20 80 00 02 08 20 80 | -..gs.....q...L..."^!........... |
14c0 | 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 dc 45 81 b8 | .............................E.. |
14e0 | 5e b7 dd c5 f9 98 ea 0e 05 ea 9a da ed d8 85 1a fb e2 c8 75 bb 50 5a 67 6a 41 17 6d cb 74 55 97 | ^..................u.PZgjA.m.tU. |
1500 | 92 5d 4b 39 d7 69 ce ba bb 7b 7d 00 aa a3 ab db ba ba 7b 2c d2 5d 4f 4f 4d b4 75 0f 16 d9 a3 4b | .]K9.i...{}.......{,.]OOM.u....K |
1520 | 8a 6d 72 c1 38 df 8e 2e da d8 ec 37 eb 70 f6 1d 2e 54 d6 13 86 99 9c 98 60 c9 49 b4 f2 e3 3b 82 | .mr.8......7.p...T......`.I...;. |
1540 | 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 | ................................ |
1560 | 08 20 80 00 02 08 dc 8e 00 81 a6 db 51 8b 81 73 ce 5e bd 61 ff fd c1 69 bb e4 5a d0 45 da d4 3a | ............Q..s.^.a...i..Z.E..: |
1580 | 6e d3 f2 29 36 75 52 a6 a9 d5 5c 6b 7b 97 dd 68 68 b7 aa ba 16 2b ad 6e 76 cf ad 3e 90 13 7e ae | n..)6uR...\k{..hh....+.nv..>..~. |
15a0 | 8e 7d 68 f6 04 7b f6 91 99 36 b3 28 cb 12 5d 8b 3a b6 c8 02 a7 2e d7 ba 50 59 bd b5 77 dc 1a 2a | .}h..{...6.(..].:.......PY..w..* |
15c0 | 9b 35 39 c7 e6 ba 6a 57 6a eb c7 86 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 | .59...jWj....................... |
15e0 | 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 30 3c 01 12 17 c3 f3 8a 99 a3 67 16 65 | ...................0<........g.e |
1600 | db f8 ac 54 2b 29 6f 74 d5 96 fa 17 d9 52 a0 69 c9 9c 7c 5b e2 c2 49 a1 5b 4f 4f af 9d b8 54 63 | ...T+)ot.....R.i..|[..I.[OO...Tc |
1620 | db 0f 5c f3 cf 0a 3a 85 6e 1a eb d0 b9 2a 1b 97 9e 64 59 e9 b3 6c 52 5e 7a e8 c7 bc 0e 11 38 72 | ..\...:.n....*...dY..lR^z.....8r |
1640 | be da 3e 3d 78 cd 9a 5b 3b 43 f6 9a 6d 59 3d cd a6 b8 0a 57 04 9a 6e 61 e1 0d 02 08 20 80 00 02 | ..>=x..[;C..mY=....W..na........ |
1660 | 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 | ................................ |
1680 | 30 24 01 ca ef 0c 89 29 f6 0e 52 e5 a4 54 57 01 48 c1 a5 e1 6c f1 ee f8 07 67 4d b0 1f 6f 9e 6b | 0$.....)..R..TW.H...l....gM..o.k |
16a0 | f3 a6 e6 46 ad c0 74 f0 4c 95 5d b8 5e 1f b1 8a d3 70 e6 bb 9f 8f 6d 6a e9 f4 6d fc ee e7 6b e4 | ...F..t.L.].^....p....mj..m...k. |
16c0 | da 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 | ..@....@....@....@....@....@.... |
16e0 | 40 00 01 04 10 40 00 81 bb 2d 40 a0 e9 6e 8b 8f e0 7c 0a 33 0d 33 cf d4 37 fb c4 dc 74 5b 31 bf | @....@...-@..n...|.3.3..7...t[1. |
1700 | c0 55 79 4a e9 db 17 fa a2 b9 ad d3 8e 5f ac b6 1b 8d ed a1 bb 79 fd b5 40 57 77 8f 35 b6 74 58 | .UyJ........._.......y..@Ww.5.tX |
1720 | 57 57 0f 26 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 | WW.&............................ |
1740 | 00 02 08 20 80 00 02 08 20 80 00 02 23 28 40 a0 69 04 31 ef f6 50 f1 71 ae 3a 93 1e b7 b9 2d 76 | ............#(@.i.1..P.q.:....-v |
1760 | 95 9a 26 64 a7 45 3d bb f2 46 ab 85 b7 a4 8b 7a f0 b7 ec 83 ea ba 36 6b 72 ad e6 7a 22 b4 fb fb | ..&d.E=..F.....z......6kr..z"... |
1780 | 96 51 70 b9 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 | .Qp............................. |
17a0 | 00 02 08 20 80 00 02 08 20 80 c0 88 0a 10 68 1a 51 ce b1 35 58 56 46 b2 25 27 45 ff 0a a8 02 51 | ..............h.Q..5XVF.%'E....Q |
17c0 | 47 57 f7 d8 ba a8 bb b4 da eb 35 4d d6 ec 02 4d 6c 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 | GW........5M...Ml............... |
17e0 | 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 23 2b 90 38 b2 c3 31 | .........................#+.8..1 |
1800 | da 58 12 48 4c 88 b7 ec 71 29 2e d4 94 60 1d 9d fd 83 4b 75 ae dd 5c 7b c7 f0 5b aa 75 f7 f4 5a | .X.HL...q)...`....Ku..\{..[.u..Z |
1820 | 93 0b 43 a9 82 51 bb 1b b7 b9 ad cb 6a 1b da ac a6 be cd cf a3 f9 d2 53 12 2d 2f 27 d5 c6 67 a6 | ..C..Q......j..........S.-/'..g. |
1840 | 5a 66 7a 92 65 67 dc 5c c7 60 05 a7 34 66 45 6d 8b b5 75 74 0d 48 9d eb c6 9d 90 93 66 c9 89 df | Zfz.eg.\.`..4fEm..ut.H......f... |
1860 | 04 b6 5a dd 39 65 d5 cd 83 56 9d ca 4c 4f 36 b5 e4 4b 49 4e e8 37 47 8f bb b6 aa ba 56 db 79 b4 | ..Z.9e...V..LO6..KIN.7G.....V.y. |
1880 | cc 2a dd 73 a4 ad a6 be d5 ce 5e b9 61 0a 8c 85 6f 1a bb c0 8d 9d 1a 61 ec e0 58 55 7d 6a 71 66 | .*.s......^.a...o......a..XU}jqf |
18a0 | 0d cd 1d de ad ae a9 dd bf 56 c0 4c f7 4c e3 e6 66 a6 38 b7 64 e7 96 6c 39 ee 5a 53 9c e9 60 76 | .........V.L.L..f.8.d..l9.ZS..`v |
18c0 | c1 f8 c1 b3 e6 51 28 ab b1 45 8f 0e 7f 5d f5 6e ae 96 f6 2e 7f 9f 54 01 2c c9 8d 9b e4 0c 33 dc | .....Q(..E...].n......T.,.....3. |
18e0 | fd d2 bc 59 ee 3e a5 a6 24 58 8e fb de 68 7e b5 3d 64 43 00 01 04 10 40 00 01 04 10 40 00 01 04 | ...Y.>..$X...h~.=dC....@....@... |
1900 | 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 46 52 80 40 d3 48 6a | .@....@....@....@....@...FR.@.Hj |
1920 | 8e c1 b1 14 f8 89 96 49 49 70 e1 99 b8 6f f2 40 83 5e 5d af 3b a2 a1 b9 dd ae 57 35 db 91 f3 d5 | .......IIp...o.@.^].;.....W5.... |
1940 | 76 c6 85 7a ca 5d f8 a8 b9 cd b5 66 73 41 a0 f0 2d ce 05 66 72 c6 25 db ac c9 d9 b6 7c 5e 81 cd | v..z.].....fsA..-..fr.%.....|^.. |
1960 | 2e ca f1 21 24 05 68 a2 6d 57 2b 1b ed 77 1f 9f b5 4b 65 f5 36 50 b7 b7 8d cb 26 db f7 d6 cd b4 | ...!$.h.mW+..w...Ke.6P....&..... |
1980 | fc dc 6f 5a ea 55 b9 16 7a bf fd f0 8c 9d bb 76 63 c0 73 97 cd 2d b0 1f 6e 9a 63 93 f3 c7 f5 2d | ..oZ.U..z......vc.s..-..n.c....- |
19a0 | 43 73 55 bb a0 92 c2 4c 5f 1c 29 b5 e3 97 6a 22 86 c0 74 c2 fe d3 95 fe d1 77 72 c8 8b 87 e6 e4 | CsU....L_.)...j"..t......wr..... |
19c0 | db 8f 36 cd b5 29 05 df 8c 1d f2 b1 0f 18 5d af 69 b6 53 25 b5 de b0 a4 bc c1 85 ca fa 87 cd 74 | ..6..)........].i.S%...........t |
19e0 | 8e 82 61 f3 a6 e6 d8 9a 85 85 36 67 f2 4d bb d0 00 57 e8 b8 e1 af 83 60 98 ee 93 ae e5 5a 45 a3 | ..a.......6g.M...W.....`.....ZE. |
1a00 | 0f 7a f5 bf 4b b7 9e a9 40 95 c2 54 9b 57 4e b5 47 16 17 45 0c 6d dd 7a 06 ef 10 40 00 01 04 10 | .z..K...@..T.WN.G..E.m.z...@.... |
1a20 | 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 | @....@....@....@....@....@....@. |
1a40 | 81 e1 09 10 68 1a 9e d7 7d 77 b4 2a 01 75 75 47 8e b1 64 b9 ca 49 c9 89 fd ab 14 45 42 50 60 a9 | ....h...}w.*.uuG..d..I.....EBP`. |
1a60 | b2 ae c5 be 38 7c dd be 3c 76 dd 57 16 0a 02 47 0a c1 e4 b8 10 4c 5a 6a a2 75 77 f7 f8 ca 4d ad | ....8|..<v.W...G.....LZj.uw...M. |
1a80 | ae 0a 90 2a 39 dd 70 55 a0 f6 9f aa b4 c3 67 ab 6d f1 ac 3c 7b 62 c5 54 9b eb 42 3a a9 c9 91 bf | ...*9.pU......g.m..<{b.T..B:.... |
1aa0 | 9a aa e8 34 77 4a 8e 1f 43 55 9f ba dc 78 43 dd 54 09 6a b6 0b 4f 29 74 55 ed aa 45 0d e7 5c 1d | ...4wJ..CU...xC.T.j..O)tU..E..\. |
1ac0 | bb 75 57 89 ed 3e 51 e6 aa 27 75 0e 18 88 1a ea 7a 42 8f eb 75 58 b2 d8 77 aa c2 fe 6f ff 55 17 | .uW..>Q..'u.....zB..uX..w...o.U. |
1ae0 | 04 6b ee 9b 43 c1 a5 cc b4 24 6f a2 16 80 aa dc a4 8a 5a 7a 1c bb 50 e3 c2 4f 37 6c e1 8c f1 f6 | .k..C....$o.......Zz..P..O7l.... |
1b00 | f4 c3 d3 6d ce 94 dc 5b aa 52 85 ce 11 bc 56 15 a6 dd c7 cb ec 93 83 d7 7c e0 2c 08 9b a9 c2 53 | ...m...[.R....V.........|.,....S |
1b20 | 9a 73 cf 48 4d f2 d5 a9 b4 5f 61 34 55 71 d2 bd d2 26 07 85 ba 6a 9c 7d e7 30 ec 83 b9 79 46 00 | .s.HM...._a4Uq...&...j.}.0...yF. |
1b40 | 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 | ...@....@....@....@....@....@... |
1b60 | 10 40 00 01 04 06 13 88 9c 1a 19 ec 2c 3e bf 2f 04 14 88 69 6e 55 a0 29 72 28 a8 70 c2 38 17 6e | .@..........,>./...inU.)r(.p.8.n |
1b80 | 19 fc 2b a2 a8 4b 69 55 93 bd f3 e5 45 3b 7c ae ca b5 83 fb a6 a2 90 aa 2d cd 2a ca b6 35 8b 0a | ..+..KiU....E;|.........-.*..5.. |
1ba0 | 6d fa a4 4c 1f 90 39 7b b5 ce 57 30 2a 77 95 88 42 83 32 07 cf 56 f9 a0 d1 f7 1f 9b 6d 0f ce cc | m..L..9{..W0*w..B.2..V......m... |
1bc0 | f3 15 88 c2 a1 27 8e 4f b7 1f 6f 9e 67 c5 ae 7a d2 1f 76 5e b4 4a 57 75 69 a8 9b da d0 fd c8 55 | .....'.O..o.g..z..v^.JWui......U |
1be0 | 5e d2 3a de fa fc a2 95 b9 f9 87 ba e9 1a e3 5d 29 2b b5 a2 d3 56 79 e3 66 e5 a9 20 b4 e5 77 7e | ^.:............])+...Vy.f.....w~ |
1c00 | fd 8f 5a b3 a9 25 9b 82 5c e1 db 24 b7 fe e4 a4 fe fb 75 1d 1f ec bd 6c 7b 4e 94 fb f6 6f c1 79 | ..Z..%..\..$......u....l{N...o.y |
1c20 | 6a 25 b7 70 46 9e 2d 9b 97 6f c5 ee 7e 28 c4 a5 63 4e b8 0a 4e 0a 56 69 d3 fd 53 a5 a5 6e 17 4c | j%.pF.-..o..~(..cN..N.Vi..S..n.L |
1c40 | 7b 6e 7d 9c cd 76 81 af a4 08 73 eb 58 05 94 b6 1f b8 66 9f 1c b8 6a 6a 65 17 6c 0a 33 15 e6 65 | {n}..v....s.X.....f...jje.l.3..e |
1c60 | d8 fc 69 e3 7d 60 4c af d5 d6 ef dc b5 3a 3b 78 a6 ca 54 19 ab b3 2b f2 f7 24 18 83 67 04 10 40 | ..i.}`L......:;x..T...+..$..g..@ |
1c80 | 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 | ....@....@....@....@....@....@.. |
1ca0 | 04 10 40 60 24 04 06 4f ab 8c c4 2c 8c 11 93 02 57 2b 9b ac a1 a5 23 e2 da 14 a4 99 3f 2d d7 57 | ..@`$..O...,....W+....#.....?-.W |
1cc0 | 56 8a 78 40 c8 ce 1b 2e 64 b3 75 4f 49 bf 30 93 0e 99 55 9c 6d 2f 3d 31 d7 87 9a d4 62 4e db e2 | V.x@....d.uOI.0...U.m/=1....bN.. |
1ce0 | 59 13 4c 95 96 de 77 e7 28 18 14 1a 0a ba e2 5a 9f 7d 76 e8 9a 4d c8 4e b3 a9 13 33 ed eb 53 fc | Y.L...w.(......Z.}v..M.N...3..S. |
1d00 | 79 c1 3f 09 2e 58 b4 6a c1 44 5f cd 68 38 81 26 9d 9f 10 1f 6f 2b 17 4c b2 bd 27 2b ac c2 b5 c3 | y.?..X.j.D_.h8.&....o+.L..'+.... |
1d20 | eb 09 9d 3c 98 20 c2 b3 82 59 2f ba a0 55 10 fe fa ff b6 9d b2 03 67 2a fb de 87 9e b2 cc b5 cf | ...<.....Y/..U........g*........ |
1d40 | db bc 62 8a 6b cd 96 1a ba db bf 56 c8 29 35 f9 d6 aa 57 0a 19 7d f8 d5 15 db e5 aa 26 a9 1a 52 | ..b.k......V.)5...W..}......&..R |
1d60 | b0 e9 da 17 4c 1f 6f 0a 78 85 5a 4c 71 2e 1d 1f 9d b1 13 ae 55 5c b0 1e 9d a3 d6 71 19 ae 92 53 | ....L.o.x.ZLq.......U\.....q...S |
1d80 | b6 0b 53 15 4d c8 08 86 e9 7b 56 28 eb 88 0b 9c ed 3a 7e fd 96 30 93 0e 48 4b 49 b4 67 d7 cd b0 | ..S.M....{V(.....:~..0..HKI.g... |
1da0 | 55 0f 4c 32 dd fb 60 7b c0 cd 3f 7d 52 96 bd f1 d9 79 bb 5c de 38 64 af e0 7c 9e 11 40 00 01 04 | U.L2..`{..?}R....y.\.8d..|..@... |
1dc0 | 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 | .@....@....@....@....@....@....@ |
1de0 | 00 81 e1 0a f4 2f 15 33 dc 11 38 7e 4c 0a a8 3a d3 fe d3 15 be 7d 58 f8 05 28 30 a4 20 8d c2 2c | ...../.3..8~L..:.....}X..(0...., |
1e00 | 6a 3f 36 d0 a6 40 cd 17 47 4a ed b8 6b 7d 16 5a 99 49 e7 24 bb 10 d0 a3 4b 8a 6d 4a 81 82 49 37 | j?6..@..GJ..k}.Z.I.$....K.mJ..I7 |
1e20 | c3 4c da af d7 eb 16 17 fa f1 53 92 fa 67 ea d4 46 ed 64 49 8d b5 b4 7f 13 ee d1 79 a1 9b 82 3b | .L........S..g..F.dI.......y...; |
1e40 | e9 ae 7a 94 d6 3a dc 4d e1 24 b5 c0 8b 54 29 29 da 58 9a 45 f3 a9 fa 92 1e 1a 23 da cc 0a 04 8d | ..z..:.M.$...T)).X.E......#..... |
1e60 | 4b bf 79 5c 70 7c f0 ac 31 54 e9 29 d8 54 55 49 6d e6 14 34 0a 0d 33 e9 73 d9 6f 5c 36 d9 26 17 | K.y\p|..1T.).TUIm..4..3.s.o\6.&. |
1e80 | 8c bb 25 d8 a5 b0 d2 92 d9 13 5c 70 29 39 18 a6 ef f9 90 ab 72 75 a9 ac 21 62 35 a5 76 57 39 eb | ..%.......\p)9......ru..!b5.vW9. |
1ea0 | 80 ab b6 54 5d d7 d6 77 7c f0 22 3f 27 cd 57 68 0a 0d 33 e9 33 dd 2b cd b5 74 6e be bb a6 81 bf | ...T]..w|."?'.Wh..3.3.+..tn..... |
1ec0 | 0b c1 58 3c 23 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 | ..X<#........................... |
1ee0 | 02 08 20 80 00 02 08 20 80 00 02 77 22 40 a0 e9 4e f4 c6 e8 b9 8d ae 2a d3 d1 0b d5 be 4d 99 5e | ...........w"@..N......*.....M.^ |
1f00 | 87 6e ca 1d a9 02 d0 77 d6 4c f3 6d dd 42 3f 8b f4 ba ac a6 c5 8d 53 d3 af e2 8f 8e 55 5b 38 3d | .n.....w.L.m.B?.......S.....U[8= |
1f20 | c2 43 32 fa 2c 35 39 d1 87 a6 14 2c 0a df 14 92 da 79 b4 cc ae a8 22 50 8f ea 0a 45 de 92 5d 70 | .C2.,59....,.....y...."P...E..]p |
1f40 | e8 76 02 4d 1a 4d 6b 8a 77 d5 9a ee f5 56 59 d7 62 bb 8e 95 59 65 5d ff d6 79 73 26 e7 fa 16 77 | .v.M.Mk.w....VY.b...Ye]..ys&...w |
1f60 | 91 ae 71 46 51 96 0b 56 f5 b7 eb e8 ea b6 93 ae 52 d3 8d c6 fe a1 a5 9a fa 56 bf 3f b4 aa 53 70 | ..qFQ..V........R........V.?..Sp |
1f80 | fd 5d 2e 58 15 b4 ff 0b f6 05 cf 0a 35 a9 aa 95 5a df 4d 71 e1 2a 3d d4 52 2f d2 ba 82 73 78 46 | .].X........5...Z.Mq.*=.R/...sxF |
1fa0 | 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 | ....@....@....@....@....@....@.. |
1fc0 | 04 10 40 00 01 04 6e 57 a0 7f 79 9c db 1d 89 f3 62 4a 40 31 20 55 fc a9 6b 6a f7 2d dd 14 62 51 | ..@...nW..y.....bJ@1.U..kj.-..bQ |
1fe0 | 55 26 3d 8e b8 0a 48 3b 5c 5b b7 ea b0 10 8d aa 0e 15 e4 a4 db 33 6b 67 d8 ec e2 9c 21 05 56 0e | U&=...H;\[...........3kg....!.V. |
2000 | 9e 71 ad db 5c db b8 48 db b4 c2 2c cb 74 95 8a a2 6d 6a a3 96 e5 aa fe 94 d7 f4 3f e2 72 79 83 | .q..\..H...,.t...mj........?.ry. |
2020 | 9d be 72 c3 8a 5d 78 26 2b ca 18 f1 4a 5f e9 71 1b 9b ce bd cd 53 6f 63 b6 e8 a7 9c 2c a9 f5 55 | ..r..]x&+...J_.q.....Soc....,..U |
2040 | b2 7a 23 b4 be 9b 3d 39 db b7 8f 8b 74 76 d1 84 71 36 ce 55 a9 8a b4 69 cc 87 17 15 9a aa 2e 85 | .z#...=9....tv..q6.U...i........ |
2060 | 56 c6 6a 74 df 87 8e ae 9e 48 a7 f8 35 5c a9 6c f4 61 a5 f4 08 55 b9 54 25 ea 87 8f cf b1 d6 f6 | V.jt.....H..5\.l.a...U.T%....... |
2080 | 2e 7f be ee 6b 66 5a f4 7b 1b 71 12 76 22 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 | ....kfZ.{.q.v".................. |
20a0 | 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 43 10 20 d0 34 04 a4 b1 78 88 2a 1b | ....................C...4...x.*. |
20c0 | 7d e5 5a 99 a9 fd 58 8f 0b cb 34 34 77 f8 00 53 95 ab d2 d3 e8 5e 87 56 e3 49 4c 88 73 c1 a3 14 | }.Z...X...44w..S.....^.V.IL.s... |
20e0 | 9b 5e 98 69 9b 96 4f b1 05 d3 c6 5b 4a 72 c2 a0 97 dd ee c2 51 1a 3f bc ca 53 70 62 5e 56 aa a5 | .^.i..O....[Jr......Q.?..Spb^V.. |
2100 | a6 44 1f 67 d2 f8 f4 be 4a 3f a1 eb d1 f9 0a 64 95 56 35 f9 50 56 b4 40 93 cf 33 05 93 0d f3 f9 | .D.g....J?.....d.V5.PV.@..3..... |
2120 | 4e ce 1d e6 54 51 0f ef 74 e1 a2 73 57 eb ac de 85 ce c2 37 c5 b4 26 64 a7 5a 5a 94 fb 90 ee 5c | N...TQ..t..sW......7..&d.ZZ....\ |
2140 | 55 65 4a 81 a5 f0 30 54 95 0b aa 95 d5 34 9b 02 51 aa 84 15 6c 6a 61 97 94 10 b9 2a 95 82 6e 1f | UeJ...0T.....4..Q...lja....*..n. |
2160 | ed bd 62 29 89 09 f6 e0 ac 3c 5f fd 29 b4 02 93 d6 a3 80 14 1b 02 08 20 80 00 02 08 20 80 00 02 | ..b).....<_.)................... |
2180 | 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 30 da 02 df a4 | ...........................0.... |
21a0 | 1d 46 7b 26 c6 bf ab 02 0a 08 ed 3f 5d 31 e8 9c aa 54 34 dd 55 52 5a fb 60 91 ad 9c 3f d1 d4 02 | .F{&.......?]1...T4.URZ.`...?... |
21c0 | 6e a8 35 8f 2a 6a 5b 5c 05 a8 8e a8 6d e1 b2 33 92 23 b6 9b 0b 16 95 e8 c2 35 b9 2e f4 a4 d6 71 | n.5.*j[\....m..3.#.......5.....q |
21e0 | 41 e5 9f e0 33 3d ab ba 54 7b 47 77 e8 ae fb ea b5 fc f4 88 54 35 49 d5 b2 14 2a eb 76 61 b4 1e | A...3=..T{Gw........T5I...*.va.. |
2200 | 17 36 8a b4 a5 b8 63 12 e3 e3 ac d3 b5 8b 0b df 54 7d ab b5 bd fb 96 40 53 7e 4e aa 0b 2a 25 bb | .6....c.........T}.....@S~N..*%. |
2220 | 56 7b 71 11 ef 99 42 50 af 7d 72 ce ae 54 34 da d2 b9 f9 36 29 2f c3 1f 1f 2d 04 15 3e 27 ef 11 | V{q...BP.}r..T4....6)/...-..>'.. |
2240 | 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 | @....@....@....@....@....@....@. |
2260 | 01 04 10 40 00 81 91 10 20 d0 34 12 8a 31 3a 46 a6 6b e7 a6 d0 50 97 0b bc a8 9a 92 2a 02 85 57 | ...@......4..1:F.k...P......*..W |
2280 | f3 49 74 a1 98 c5 b3 26 b8 47 9e ab d2 94 34 e4 30 93 2e b9 bc b6 d9 5a da 3a a3 5e 7d 9a ab 08 | .It....&.G....4.0......Z.:.^}... |
22a0 | a4 f9 07 da 52 5d 68 47 15 a2 22 6d 3e d0 14 25 cc 13 e9 f8 b1 b6 af a6 a1 d5 da 3a 6e b6 70 0b | ....R]hG.."m>..%...........:n.p. |
22c0 | 5f bb ee cb c5 d2 86 01 03 5d f5 ae d2 56 b4 1b 76 a3 b1 fd eb b1 53 fa 86 56 b5 a6 39 93 73 ec | _........]...V..v.....S..V..9.s. |
22e0 | e2 f5 7a d3 e7 91 36 99 7f b0 f7 b2 ed 3d 59 61 4b 66 4f b0 65 f3 0a 6c 72 fe 38 1f 74 4b 76 6b | ..z...6......=YaKfO.e..lr.8.tKvk |
2300 | 62 43 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 | bC....@....@....@....@....@....@ |
2320 | 00 01 04 10 40 00 01 04 46 5b 80 40 d3 68 0b df a3 f1 d5 2e 6c cd c2 42 2b 9a 90 e1 5b c2 95 bb | ....@...F[.@.h......l..B+...[... |
2340 | 4a 40 17 4a eb ad da b5 9c eb 0e a9 e8 a3 56 63 ef ed 2c 31 b5 29 7b f4 a1 62 9b 51 a8 36 65 d1 | J@.J..........Vc..,1.){..b.Q.6e. |
2360 | db c4 85 5e 4e 4b 6b 97 0b 4b f5 84 ee ba e5 b5 2a fb a8 02 d4 40 9b da a6 25 c4 47 0e ca d4 37 | ...^NKk..K......*....@...%.G...7 |
2380 | 76 b8 50 4e e4 ea 44 03 8d 39 56 3e 6b 6a ed f4 21 b3 48 eb 6d 69 eb b2 77 77 5e 8c f4 d1 90 f6 | v.PN..D..9V>kj..!.H.mi..ww^..... |
23a0 | b5 b4 eb de f4 af dc f4 c8 92 22 bb e6 5a f9 ed 3f 5d 19 35 4c a5 09 6e 34 b6 d9 67 87 ae d9 3e | .........."..Z..?].5L..n4..g...> |
23c0 | d7 b6 70 d1 cc 3c 7b 78 d1 24 9b 55 9c dd af 15 dd 90 16 c3 41 08 20 80 00 02 08 20 80 00 02 08 | ..p..<{x.$.U........A........... |
23e0 | 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 c0 30 04 08 34 | ............................0..4 |
2400 | 0d 03 6b 2c 1d aa 40 d3 43 73 f2 7d 95 1d ad 5b c1 a3 2f 8e 5e b7 6d bb 4b ac bc a6 c5 7a 5c 2b | ..k,..@.Cs.}...[../.^.m.K....z\+ |
2420 | b3 60 eb e8 ea b6 2f 8e 5c b7 ab 95 4d f6 e2 63 b3 ed 81 19 79 36 94 6a 3c ad 2e 6c 14 29 34 a3 | .`..../.\...M..c....y6.j<..l.)4. |
2440 | 71 15 63 d2 1a 06 c9 33 f9 f0 54 42 94 0a 4d ad ae 7a 91 5a d1 a9 7d 9e c6 ba df b6 66 17 08 eb | q.c....3..TB..M..z.Z..}.....f... |
2460 | 8c 12 08 53 65 ab b4 94 c4 a8 d5 ab 06 b3 50 bb ba 48 f6 39 e3 52 ec 89 95 53 7d 90 ea f8 c5 1a | ...Se.........P..H.9.R...S}..... |
2480 | 6b 69 ef 74 55 bb a2 8f d6 ec 2a 70 ed 3d 59 6e 27 4b 6a ed 91 c5 85 b6 61 e9 64 2b 74 ad e8 ee | ki.tU.....*p.=Yn'Kj.....a.d+t... |
24a0 | c7 fb 11 5d 81 4f 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 | ...].O.@....@....@....@....@.... |
24c0 | 40 00 01 04 10 40 00 01 04 10 40 e0 6e 0a 10 68 ba 9b da f7 70 2e 05 64 1e 5d 52 6c 35 f5 6d f6 | @....@....@.n..h....p..d.]Rl5.m. |
24e0 | c9 fe ab d6 d0 e2 da 95 85 6d 25 65 0d b6 fd c0 55 df 5e 6c ea c4 cc 41 ab 2b 29 24 15 1a 8c ba | .........m%e....U.^l...A.+)$.... |
2500 | 65 38 97 a6 d1 67 ca ca 0c 14 45 4a 4a 4c b0 f8 01 c2 4a dd 3d 41 9b bc 81 46 b9 65 e6 31 f3 a6 | e8...g....EJJL....J.=A...F.e.1.. |
2520 | d3 05 c9 7a 5c 58 2b d2 96 95 91 6c 6b 1e 98 64 13 72 d2 22 7d 3c e8 be dc cc 14 cb 4a 4f 8e 78 | ...z\X+....lk..d.r."}<......JO.x |
2540 | dc 6c 57 69 e9 87 8f cf f1 f7 f9 e8 f9 6a 5f b5 4b ed 08 07 da 1a dd f7 e5 c3 af ae 58 47 67 8f | .lWi.........j_.K...........XGg. |
2560 | 6d 59 3d d5 26 8d cf 18 f0 be 0d 34 16 9f 21 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 | mY=.&......4..!................. |
2580 | 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 03 09 10 68 1a 48 e7 3e fb 4c 55 | ........................h.H.>.LU |
25a0 | 75 d6 2e 2a b4 73 57 eb ec d4 e5 da 88 61 9a a3 17 6a 7c 6b b1 f1 59 a9 51 03 31 01 8b 5a d3 25 | u..*.sW......a...j|k..Y.Q.1..Z.% |
25c0 | 46 69 17 d7 eb c2 4c ed ae 9d 5d b7 0b 3d 29 4c 15 6d d3 71 3e f5 14 e1 00 ad 37 2d 25 c9 12 06 | Fi....L...]..=)L.m.q>.....7-%... |
25e0 | 38 3f c2 69 37 77 45 1f 36 ea 29 23 f5 81 af 78 14 39 a7 74 cb 14 19 69 49 96 94 18 d9 46 fb 97 | 8?.i7wE.6.)#...x.9.t...iI....F.. |
2600 | cf 2f b0 79 53 73 6f 39 67 a4 de 4c 1c 9f 6e 3f d8 38 db e6 4e c9 b1 3d c7 cb ed 72 45 83 6b 33 | ./.ySso9g..L..n?.8..N..=...rE.k3 |
2620 | d7 1e b5 05 9e e6 55 f8 6a c7 e1 52 53 f5 a7 a7 56 4f 33 7d 47 d8 10 40 00 01 04 10 40 00 01 04 | ......U.j..RS...VO3}G..@....@... |
2640 | 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 81 91 16 88 | .@....@....@....@....@....@..... |
2660 | 9c a6 18 e9 59 18 2f 66 04 8a 26 64 d8 03 d3 73 2d 33 3d 29 e2 9a 14 40 52 fb b9 8b a5 f5 3e 8c | ....Y./f..&d...s-3=)...@R.....>. |
2680 | 14 f1 a0 af 77 66 a4 26 59 62 62 f4 ca 49 6d ae 25 9d da c5 0d b4 b5 bb 8a 3f d1 8e 51 cb 35 b5 | ....wf.&Ybb..Im.%........?..Q.5. |
26a0 | be 8b 3e 43 f4 91 5d 5d 27 f7 e1 c0 73 47 3f fb ce 3e 51 48 6b 28 33 ab fd 5b 4a 52 42 c4 c9 9a | ..>C..]]'...sG?..>QHk(3..[JRB... |
26c0 | 5a 3b ad 63 90 aa 49 11 4f 1c c6 ce d4 e4 44 5b ed aa 40 fd f2 7b 8b 5c b8 69 ae 2d 75 2d 0a 27 | Z;.c..I.O.....D[..@..{.\.i.-u-.' |
26e0 | b9 a0 53 72 94 35 69 68 55 e5 fa f4 c0 35 bb e4 aa 79 45 ad ce 35 8c 35 70 28 02 08 20 80 00 02 | ..Sr.5ihU....5...yE..5.5p(...... |
2700 | 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 | ................................ |
2720 | 10 2e 40 a0 29 5c e4 5b f0 7e e9 dc 02 2b cc 73 2d c3 5c 5b b8 48 5b 45 6d 8b 1d 3a 5b e5 2b f6 | ..@.)\.[.~...+.s-.\[.H[Em..:[.+. |
2740 | 44 fa 3c d8 e7 2b 0c 25 44 0e e4 e8 98 76 05 9a ba 07 8e f6 74 a8 8a 53 94 d0 d3 38 17 ba 8a 56 | D.<..+.%D....v......t..S...8...V |
2760 | c1 48 e3 c7 45 59 bf 3e 53 35 21 5f 29 49 6f ee f2 a6 eb f1 95 a7 06 99 37 db 05 9a a2 85 87 5a | .H..EY.>S5!_)Io.........7......Z |
2780 | db bb bc df dd 08 0d a5 a7 26 da c3 8b 26 d9 9f 3e f7 a0 fd 78 f3 3c 7b c8 05 9b b4 b6 68 df 8f | .........&...&..>...x.<{.....h.. |
27a0 | d6 8e 2e 2b 77 df 11 ad 91 0d 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 | ...+w........@....@....@....@... |
27c0 | 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 18 69 01 02 4d 23 2d 3a 06 c6 9b 52 30 ce 66 4f | .@....@....@.....i..M#-:...R0.fO |
27e0 | ce 31 05 59 a2 6d 47 2e 54 5b 69 75 73 d4 b0 91 ce 53 85 21 b5 9d 8b b6 35 bb 2a 43 9d 83 54 19 | .1.Y.mG.T[ius....S.!....5.*C..T. |
2800 | 52 38 46 55 a1 22 6d 93 c6 67 b8 35 46 ae 24 a5 e3 15 b8 89 16 6a ea 18 a0 f2 93 ce ed 74 73 de | R8FU."m..g.5F.$......j.......ts. |
2820 | 49 58 c8 47 c1 22 e7 c1 7c 15 a3 a1 04 9a 72 c6 25 47 ad d0 a4 40 56 e5 8d bb 1b 1a d2 bd 5c 3e | IX.G."..|.....r.%G...@V.......\> |
2840 | af c0 7e f1 dd 07 6c d3 f2 29 ae a5 5c 4a 54 df eb 55 4d a6 fb cb 86 00 02 08 20 80 00 02 08 20 | ..~...l..)..\JT..UM............. |
2860 | 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 8c b4 00 | ................................ |
2880 | 81 a6 91 16 1d 03 e3 29 04 b4 6c 6e be 4d 74 ed c5 a2 15 39 aa ae 6b b5 53 25 b5 d6 d0 dc 11 f5 | .......)..ln.Mt....9..k.S%...... |
28a0 | 8a d4 be 6e 42 4e 9a 25 26 44 fe 1a 5d 77 81 a8 e6 b6 e8 a1 17 55 6f ba d1 d0 ee 2b 11 85 4f a2 | ...nBN.%&D..]w.......Uo....+..O. |
28c0 | b0 d2 bc a9 b9 96 9b 99 12 fe 51 df fb e4 a4 78 4b 88 8f 9c 2a 52 cb b6 68 61 2a 55 8e aa ad 6f | ..........Q....xK...*R..ha*U...o |
28e0 | b3 76 57 1d ea 76 b7 64 17 fe 89 36 77 6b 5b 57 d4 b9 43 e7 cb 4c 4f 36 55 b9 8a 8f 72 0d c7 5c | .vW..v.d...6wk[W..C..LO6U...r..\ |
2900 | a8 ac ba ae 2d f4 94 01 5f b7 38 6b 5d 77 b4 8a 57 55 ee 9e 5e a9 68 b4 cb e5 8d 3e 2c 15 cd 47 | ....-..._.8k]w..WU..^.h....>,..G |
2920 | 6b 7a fa e1 e9 ee 3b 52 60 69 29 91 03 6b 0d 2d 1d a6 d0 18 1b 02 08 20 80 00 02 08 20 80 00 02 | kz....;R`i)..k.-................ |
2940 | 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 30 d2 02 91 93 | ...........................0.... |
2960 | 28 23 3d 0b e3 8d 8a 80 af 30 14 a5 af da cd 46 6f d1 db bd cd 2a ca b6 19 85 59 ae c2 52 f4 2a | (#=......0.....Fo....*....Y..R.* |
2980 | 4d 07 cf 56 5a a9 ab c4 13 2d 20 a3 76 70 73 5c a5 a7 6c 57 69 28 d2 a6 f0 cc 40 81 a8 da c6 36 | M..VZ....-..vps\..lWi(....@....6 |
29a0 | ab 69 68 f5 d5 92 c2 cf cf ca 48 b6 e9 6e 7d 19 03 54 68 4a 4b 49 b4 84 84 c8 81 a6 f2 da 66 17 | .ih.......H..n}..ThJKI........f. |
29c0 | ee e9 e8 d7 76 4e 5c 17 ae d7 bb 40 4f 6b d4 76 78 9e 34 3a 9d 5f 6a b6 5b 5f b4 76 71 d5 f5 ad | ....vN\....@Ok.vx.4:._j.[_.vq... |
29e0 | d6 e2 da b1 85 0f 11 fe 5e 41 30 55 ca ca ce 88 1c da 3a 7b b5 ce 2e b9 b5 b6 b9 2a 56 83 6d 0a | ........^A0U......:{.......*V.m. |
2a00 | 18 ed 3e 51 6e 9f 1e bc 66 65 35 91 2b 6b 6d db 53 62 ff fc fa 11 fb 7f 5f 3f 6c af 6e 3f e7 da | ..>Qn...fe5.+km.Sb......_?l.n?.. |
2a20 | c6 35 47 1d 56 d5 9a e6 4c c9 8d ba b6 bc ac d4 01 ab 73 45 1d 98 0f 10 40 00 01 04 10 40 00 01 | .5G.V...L.........sE....@....@.. |
2a40 | 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 81 41 04 | ..@....@....@....@....@....@..A. |
2a60 | 08 34 0d 02 14 cb 1f ab 55 9b eb 4c 16 71 53 08 a9 67 80 02 3a 09 2e 4c b3 62 fe c4 01 ab 34 a9 | .4......U..L.qS..g..:..L.b....4. |
2a80 | c2 d2 51 57 25 a8 a1 b9 3d e2 1c da 39 7f 5a ae 4d 72 95 9e 22 55 2b aa aa 6b f1 a1 99 68 95 90 | ..QW%...=...9.Z.Mr.."U+..k...h.. |
2aa0 | 2e 95 d5 47 0c 3c 25 ba 90 d2 92 d9 f9 56 e0 aa 3f 45 ab 20 a5 b9 d5 f2 2e 25 29 72 05 a1 5a 57 | ...G.<%......V..?E.......%)r..ZW |
2ac0 | f9 e9 b2 0b 54 b5 b4 7f 53 21 4a 6d dc 14 e2 f9 e2 c8 75 ab 70 ed dc a2 6d dd 0e 6e b0 76 74 0a | ....T...S!Jm......u.p...m..n.vt. |
2ae0 | 21 45 9b fb 6a 65 93 5d 75 73 b7 87 04 91 3a 5c 35 28 b5 69 53 d8 a9 2b a4 c5 de ea 05 13 5d 70 | !E..je.]us....:\5(.iS..+......]p |
2b00 | 2b 33 62 95 2b b9 ed 38 5c ea ef 81 2a 2f 85 67 d7 d4 d6 ae cd 55 9b 52 80 69 fb fe ab f6 ee 17 | +3b.+..8\...*/.g.....U.R.i...... |
2b20 | 17 ed f5 cf ce db 97 47 af 47 74 ad 6b 6c f7 d7 5d 51 db 62 47 ce 55 d9 e5 b2 46 57 65 29 7a 95 | .......G.Gt.kl..]Q.bG.U...FWe)z. |
2b40 | aa 71 e9 49 a6 d0 5a a4 6d 52 de c0 ed 00 23 9d c3 3e 04 10 40 00 01 04 10 40 00 01 04 10 40 00 | .q.I..Z.mR....#..>..@....@....@. |
2b60 | 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 60 28 02 d1 cb f3 0c e5 | ...@....@....@....@....@`(...... |
2b80 | 6c 8e b9 67 02 0a c5 28 cc a2 90 4e a4 4d fb 55 25 48 c7 45 6b 09 a7 96 6e aa d4 54 5e d3 12 b5 | l..g...(...N.M.U%H.Ek...n..T^... |
2ba0 | 0a d0 57 a7 2a 6c 76 71 b6 3d e4 5a d4 25 27 f6 0f 0f 4d 29 18 67 cb e6 15 f8 8a 47 0a eb 84 86 | ..W.*lvq.=.Z.%'...M).g.....G.... |
2bc0 | 6e 14 aa da 77 aa d2 a6 14 64 fa 6a 4b a1 a1 a7 ba a6 76 3b 74 b6 da 6a 1b fa b7 54 d3 f1 eb 97 | n...w....d.jK.....v;t..j...T.... |
2be0 | 14 5a be 0b 34 0d b4 15 e7 67 58 a6 0b dd a8 95 5a f8 a6 b0 8f c2 40 e3 5c fb 34 5d a3 94 ea 9b | .Z..4....gX.....Z.....@.\.4].... |
2c00 | 3a 6c fb 81 ab a6 56 6e f2 d1 7a 22 55 9f 52 9b bc d0 d0 51 f8 d8 7a 5f 90 9b 66 e9 a9 91 ff d7 | :l....Vn..z"U.R....Q..z_..f..... |
2c20 | 47 e7 ee 39 59 ee db c9 15 4f 18 e7 c3 51 0a 87 7d e2 e6 56 f8 6b cb ea 69 56 e8 da f5 a9 ad 9e | G..9Y....O...Q..}..V.k..iV...... |
2c40 | 5a f6 ad 98 37 d1 85 9d 9a 23 86 ac ce 5d ab b3 86 ed 1d f6 f8 f2 36 57 0d 2b db d2 53 92 7c 55 | Z...7....#...]........6W.+..S.|U |
2c60 | 2a cd d1 ec 42 4e e5 b5 ad b6 d7 cd 75 ee ea 0d ff 7d 50 d5 28 cd a5 ea 54 03 b5 eb 6b 73 41 26 | *...BN......u....}P.(...T...ksA& |
2c80 | ad 51 6d 07 67 14 65 f5 fb 8e c8 a7 c2 05 a5 f4 1d 0a df d4 2a af d0 05 9a a2 b5 a3 0b 3f 9e f7 | .Qm.g.e.............*........?.. |
2ca0 | 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 | ................................ |
2cc0 | 80 00 02 08 20 80 c0 70 04 22 27 32 86 33 02 c7 de 75 01 85 4d 4a ca 1b ec 86 ab b8 33 50 25 a1 | .......p."'2.3...u..MJ......3P%. |
2ce0 | 8b a5 f5 be 25 5c 7e 4e aa ab 74 d4 bf 35 9b aa ef ac 74 15 82 d4 82 ed b2 1b 2f 34 8c 14 5c 54 | ....%\~N..t..5....t......./4..\T |
2d00 | b5 0b 0b 7d 76 a8 d4 87 73 d4 5e 2e bc cd 9a c6 5d bf b8 d8 2a 5c b0 66 f7 f1 b2 7e 6d de 14 1e | ...}v...s.^.....]...*\.f...~m... |
2d20 | 9a 38 3e cd 8d dd eb c3 3b 5a 85 42 32 3a f6 c4 a5 1a 1f c2 09 e6 52 c0 27 2f 3b d5 07 7e a6 17 | .8>.....;Z.B2:........R.'/;..~.. |
2d40 | 66 5b bc 0b 1c 0d b4 15 e7 8f f3 81 1c 55 44 ea ec ea 5f 8e aa d4 ed 7f e5 a3 33 56 e4 c2 37 0a | f[...........UD..._.......3V..7. |
2d60 | 2e 95 bb 80 8e aa 1e 29 44 a4 60 d1 e5 f2 46 53 b0 2a 7c 53 3b 3a 55 31 d2 f8 d1 aa 30 cd 2a ce | .......)D.`...FS.*|S;:U1....0.*. |
2d80 | b1 a9 2e 78 a5 30 58 a4 0a 54 27 2f d5 fa 0a 48 05 ee da 3b 3a 7b 7c e8 4a d5 90 b4 d6 f9 d3 c7 | ...x.0X..T'/...H...;:{|.J....... |
2da0 | fb b0 56 60 b9 dc 05 c2 ce b8 40 52 7d 73 47 c4 60 99 d6 f2 bb 8f cf f8 f6 7b 0a 79 a9 72 92 d6 | ..V`......@R}sG.`........{.y.r.. |
2dc0 | 5d e5 d6 19 3a b7 5a f0 3d e0 c6 7e 6e fd 4c 53 90 6a b0 ed c8 f9 6a 1f f8 5a df 55 e4 3c 32 2c | ]...:.Z.=..~n.LS.j....j..Z.U.<2, |
2de0 | c5 b5 99 93 78 a7 0b 4b 29 24 b6 ff 4c a5 fb 8e dd 1a 38 d3 1c eb 1e 2c 74 e3 67 44 fc 4e 0d 36 | ....x..K)$..L.....8....,t.gD.N.6 |
2e00 | 27 9f 23 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 20 80 00 02 08 | '.#............................. |
2e20 | 20 80 00 02 08 20 80 00 02 83 09 24 fc 3f 6e 1b ec 20 3e 8f 1d 01 b5 1e 2b a9 68 b0 8f f6 5e b1 | ...........$.?n...>.....+.h...^. |
2e40 | f3 2e b0 34 50 25 21 55 3f 52 20 27 23 35 c9 55 d3 49 74 95 7d fa b7 0f cb cd 4c f5 e1 9d eb d5 | ...4P%!U?R.'#5.U.It.}.....L..... |
2e60 | 2d 11 43 41 ba f2 4a d7 9e ed 86 0b d0 a4 24 27 fa 60 93 c6 0c 0d 48 29 18 a5 4a 3f ed ae 62 94 | -.CA..J.......$'.`....H)..J?..b. |
2e80 | aa 20 29 64 13 84 a3 54 19 e9 8a 6b bf 56 e2 da 9b dd 70 6d e0 2e b8 35 ab 72 d2 be d3 15 b7 b4 | ..)d...T...k.V....pm...5.r...... |
2ea0 | 45 d3 98 aa f6 f4 f4 c3 d3 7d c5 a7 68 d5 8f 42 ef 84 af 18 d5 1b 67 65 ae 22 51 43 4b 47 df 9c | E........}..h..B......ge."QCKG.. |
2ec0 | a1 c7 28 e8 24 07 85 bf 14 90 9a 32 31 d3 9e 7b 64 a6 9f eb 92 0b 71 35 b8 10 51 f8 a6 e0 51 4b | ..(.$......21..{d.....q5..Q...QK |
2ee0 | 5b 97 6f b7 96 e1 2a 3c 69 6d 0a 5b 85 6e ba 66 55 be d2 dc 0a 22 05 d7 1b 7a 8c e6 56 9b b7 46 | [.o...*<im.[.n.fU...."...z..V..F |
2f00 | b7 36 97 a7 f2 2d f2 d4 4a 6f d9 dc 02 5f 3d 29 30 54 b0 69 7c 56 aa 35 b9 e3 34 56 97 3b 2f 52 | .6...-..Jo..._=)0T.i|V.5..4V.;/R |
2f20 | dd 2d 3f 9e bb 0f 0a 5c 69 dd 41 75 29 55 9a ca cb 4a f3 e3 ea da a6 4e cc 8a 18 06 53 25 a7 eb | .-?....\i.Au)U...J.....N....S%.. |
2f40 | 2e d4 15 ba 56 dd 9b f3 a5 75 56 e9 42 53 0a 31 5d a9 68 f2 15 ac b6 ed b9 ec 43 73 dd dd 37 57 | ....V....uV.BS.1].h.......Cs..7W |
2f60 | a2 ab d7 3d 51 f8 ea 29 77 8f 74 bf d9 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 | ...=Q..)w.t...@....@....@....@.. |
2f80 | 04 10 40 00 01 04 10 40 00 01 04 10 40 00 01 04 10 40 00 81 d1 10 20 d0 34 1a aa a3 38 e6 a1 73 | ..@....@....@....@......4...8..s |
2fa0 | d5 f6 3f ae 5a cf e9 92 5a 5f 49 67 a0 a9 d4 92 ee 54 c9 0d 1f e6 99 5e 98 65 59 19 c9 fd 0e 57 | ..?.Z...Z_Ig.....T.....^.eY....W |
2fc0 | 18 46 fb af 56 36 fa e0 4f 68 d8 25 f4 60 85 68 0e bb 8a 3e 39 19 29 56 e4 aa f3 04 d5 85 82 63 | .F..V6..Oh.%.`.h...>9.)V.......c |
2fe0 | d4 da 4d 2d ec 52 5d 95 1f b5 33 53 45 26 55 92 52 05 29 05 6f 14 28 52 fb b4 b3 57 5d 78 c6 8d | ..M-.R]...3SE&U.R.).o.(R...W]x.. |
3000 | a5 70 8e e6 1e 97 96 6c 13 5c 55 26 55 16 fa a3 0d b3 6c b1 0b fc a4 ba e0 d4 5/*
* Copyright (c) 2011-2016 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* @brief BFD nodes implementation
*/
#if WITH_LIBSSL > 0
#include <openssl/sha.h>
#endif
#if __SSE4_2__
#include <x86intrin.h>
#endif
#include <vlibmemory/api.h>
#include <vppinfra/random.h>
#include <vppinfra/error.h>
#include <vppinfra/hash.h>
#include <vppinfra/xxhash.h>
#include <vnet/ethernet/ethernet.h>
#include <vnet/ethernet/packet.h>
#include <vnet/bfd/bfd_debug.h>
#include <vnet/bfd/bfd_protocol.h>
#include <vnet/bfd/bfd_main.h>
#include <vlib/log.h>
static u64
bfd_calc_echo_checksum (u32 discriminator, u64 expire_time, u32 secret)
{
u64 checksum = 0;
#if defined(clib_crc32c_uses_intrinsics) && !defined (__i386__)
checksum = crc32_u64 (0, discriminator);
checksum = crc32_u64 (checksum, expire_time);
checksum = crc32_u64 (checksum, secret);
#else
checksum = clib_xxhash (discriminator ^ expire_time ^ secret);
#endif
return checksum;
}
static u64
bfd_usec_to_nsec (u64 us)
{
return us * NSEC_PER_USEC;
}
u32
bfd_nsec_to_usec (u64 nsec)
{
return nsec / NSEC_PER_USEC;
}
always_inline u64
bfd_time_now_nsec (vlib_main_t * vm, f64 * vm_time)
{
f64 _vm_time = vlib_time_now (vm);
if (vm_time)
*vm_time = _vm_time;
return _vm_time * NSEC_PER_SEC;
}
static vlib_node_registration_t bfd_process_node;
u8 *
format_bfd_auth_key (u8 * s, va_list * args)
{
const bfd_auth_key_t *key = va_arg (*args, bfd_auth_key_t *);
if (key)
{
s = format (s, "{auth-type=%u:%s, conf-key-id=%u, use-count=%u}, ",
key->auth_type, bfd_auth_type_str (key->auth_type),
key->conf_key_id, key->use_count);
}
else
{
s = format (s, "{none}");
}
return s;
}
/*
* We actually send all bfd pkts to the "error" node after scanning
* them, so the graph node has only one next-index. The "error-drop"
* node automatically bumps our per-node packet counters for us.
*/
typedef enum
{
BFD_INPUT_NEXT_NORMAL,
BFD_INPUT_N_NEXT,
} bfd_input_next_t;
static void bfd_on_state_change (bfd_main_t * bm, bfd_session_t * bs, u64 now,
int handling_wakeup);
static void
bfd_set_defaults (bfd_main_t * bm, bfd_session_t * bs)
{
bs->local_state = BFD_STATE_down;
bs->local_diag = BFD_DIAG_CODE_no_diag;
bs->remote_state = BFD_STATE_down;
bs->remote_discr = 0;
bs->hop_type = BFD_HOP_TYPE_SINGLE;
bs->config_desired_min_tx_usec = BFD_DEFAULT_DESIRED_MIN_TX_USEC;
bs->config_desired_min_tx_nsec = bm->default_desired_min_tx_nsec;
bs->effective_desired_min_tx_nsec = bm->default_desired_min_tx_nsec;
bs->remote_min_rx_usec = 1;
bs->remote_min_rx_nsec = bfd_usec_to_nsec (bs->remote_min_rx_usec);
bs->remote_min_echo_rx_usec = 0;
bs->remote_min_echo_rx_nsec = 0;
bs->remote_demand = 0;
bs->auth.remote_seq_number = 0;
bs->auth.remote_seq_number_known = 0;
bs->auth.local_seq_number = random_u32 (&bm->random_seed);
bs->echo_secret = random_u32 (&bm->random_seed);
}
static void
bfd_set_diag (bfd_session_t * bs, bfd_diag_code_e code)
{
if (bs->local_diag != code)
{
BFD_DBG ("set local_diag, bs_idx=%d: '%d:%s'", bs->bs_idx, code,
bfd_diag_code_string (code));
bs->local_diag = code;
}
}
static void
bfd_set_state (vlib_main_t * vm, bfd_main_t * bm, bfd_session_t * bs,
bfd_state_e new_state, int handling_wakeup)
{
if (bs->local_state != new_state)
{
BFD_DBG ("Change state, bs_idx=%d: %s->%s", bs->bs_idx,
bfd_state_string (bs->local_state),
bfd_state_string (new_state));
bs->local_state = new_state;
bfd_on_state_change (bm, bs, bfd_time_now_nsec (vm, NULL),
handling_wakeup);
}
}
const char *
bfd_poll_state_string (bfd_poll_state_e state)
{
switch (state)
{
#define F(x) \
case BFD_POLL_##x: \
return "BFD_POLL_" #x;
foreach_bfd_poll_state (F)
#undef F
}
return "UNKNOWN";
}
static void
bfd_set_poll_state (bfd_session_t * bs, bfd_poll_state_e state)
{
if (bs->poll_state != state)
{
BFD_DBG ("Setting poll state=%s, bs_idx=%u",
bfd_poll_state_string (state), bs->bs_idx);
bs->poll_state = state;
}
}
static void
bfd_recalc_tx_interval (bfd_main_t * bm, bfd_session_t * bs)
{
bs->transmit_interval_nsec =
clib_max (bs->effective_desired_min_tx_nsec, bs->remote_min_rx_nsec);
BFD_DBG ("Recalculated transmit interval " BFD_CLK_FMT,
BFD_CLK_PRN (bs->transmit_interval_nsec));
}
static void
bfd_recalc_echo_tx_interval (bfd_main_t * bm, bfd_session_t * bs)
{
bs->echo_transmit_interval_nsec =
clib_max (bs->effective_desired_min_tx_nsec, bs->remote_min_echo_rx_nsec);
BFD_DBG ("Recalculated echo transmit interval " BFD_CLK_FMT,
BFD_CLK_PRN (bs->echo_transmit_interval_nsec));
}
static void
bfd_calc_next_tx (bfd_main_t * bm, bfd_session_t * bs, u64 now)
{
if (bs->local_detect_mult > 1)
{
/* common case - 75-100% of transmit interval */
bs->tx_timeout_nsec = bs->last_tx_nsec +
(1 - .25 * (random_f64 (&bm->random_seed))) *
bs->transmit_interval_nsec;
if (bs->tx_timeout_nsec < now)
{
/*
* the timeout is in the past, which means that either remote
* demand mode was set or performance/clock issues ...
*/
BFD_DBG ("Missed %lu transmit events (now is %lu, calc "
"tx_timeout is %lu)",
(now - bs->tx_timeout_nsec) /
bs->transmit_interval_nsec, now, bs->tx_timeout_nsec);
bs->tx_timeout_nsec = now;
}
}
else
{
/* special case - 75-90% of transmit interval */
bs->tx_timeout_nsec = bs->last_tx_nsec +
(.9 - .15 * (random_f64 (&bm->random_seed))) *
bs->transmit_interval_nsec;
if (bs->tx_timeout_nsec < now)
{
/*
* the timeout is in the past, which means that either remote
* demand mode was set or performance/clock issues ...
*/
BFD_DBG ("Missed %lu transmit events (now is %lu, calc "
"tx_timeout is %lu)",
(now - bs->tx_timeout_nsec) /
bs->transmit_interval_nsec, now, bs->tx_timeout_nsec);
bs->tx_timeout_nsec = now;
}
}
if (bs->tx_timeout_nsec)
{
BFD_DBG ("Next transmit in %lu nsec/%.02fs@%lu",
bs->tx_timeout_nsec - now,
(bs->tx_timeout_nsec - now) * SEC_PER_NSEC,
bs->tx_timeout_nsec);
}
}
static void
bfd_calc_next_echo_tx (bfd_main_t * bm, bfd_session_t * bs, u64 now)
{
bs->echo_tx_timeout_nsec =
bs->echo_last_tx_nsec + bs->echo_transmit_interval_nsec;
if (bs->echo_tx_timeout_nsec < now)
{
/* huh, we've missed it already, transmit now */
BFD_DBG ("Missed %lu echo transmit events (now is %lu, calc tx_timeout "
"is %lu)",
(now - bs->echo_tx_timeout_nsec) /
bs->echo_transmit_interval_nsec,
now, bs->echo_tx_timeout_nsec);
bs->echo_tx_timeout_nsec = now;
}
BFD_DBG ("Next echo transmit in %lu nsec/%.02fs@%lu",
bs->echo_tx_timeout_nsec - now,
(bs->echo_tx_timeout_nsec - now) * SEC_PER_NSEC,
bs->echo_tx_timeout_nsec);
}
static void
bfd_recalc_detection_time (bfd_main_t * bm, bfd_session_t * bs)
{
if (bs->local_state == BFD_STATE_init || bs->local_state == BFD_STATE_up)
{
bs->detection_time_nsec =
bs->remote_detect_mult *
clib_max (bs->effective_required_min_rx_nsec,
bs->remote_desired_min_tx_nsec);
BFD_DBG ("Recalculated detection time %lu nsec/%.3fs",
bs->detection_time_nsec,
bs->detection_time_nsec * SEC_PER_NSEC);
}
}
static void
bfd_set_timer (bfd_main_t * bm, bfd_session_t * bs, u64 now,
int handling_wakeup)
{
u64 next = 0;
u64 rx_timeout = 0;
u64 tx_timeout = 0;
if (BFD_STATE_up == bs->local_state)
{
rx_timeout = bs->last_rx_nsec + bs->detection_time_nsec;
}
if (BFD_STATE_up != bs->local_state ||
(!bs->remote_demand && bs->remote_min_rx_usec) ||
BFD_POLL_NOT_NEEDED != bs->poll_state)
{
tx_timeout = bs->tx_timeout_nsec;
}
if (tx_timeout && rx_timeout)
{
next = clib_min (tx_timeout, rx_timeout);
}
else if (tx_timeout)
{
next = tx_timeout;
}
else if (rx_timeout)
{
next = rx_timeout;
}
if (bs->echo && next > bs->echo_tx_timeout_nsec)
{
next = bs->echo_tx_timeout_nsec;
}
BFD_DBG ("bs_idx=%u, tx_timeout=%lu, echo_tx_timeout=%lu, rx_timeout=%lu, "
"next=%s",
bs->bs_idx, tx_timeout, bs->echo_tx_timeout_nsec, rx_timeout,
next == tx_timeout
? "tx" : (next == bs->echo_tx_timeout_nsec ? "echo tx" : "rx"));
if (next)
{
int send_signal = 0;
bs->event_time_nsec = next;
/* add extra tick if it's not even */
u32 wheel_time_ticks =
(bs->event_time_nsec - now) / bm->nsec_per_tw_tick +
((bs->event_time_nsec - now) % bm->nsec_per_tw_tick != 0);
BFD_DBG ("event_time_nsec %lu (%lu nsec/%.3fs in future) -> "
"wheel_time_ticks %u", bs->event_time_nsec,
bs->event_time_nsec - now,
(bs->event_time_nsec - now) * SEC_PER_NSEC, wheel_time_ticks);
wheel_time_ticks = wheel_time_ticks ? wheel_time_ticks : 1;
bfd_lock (bm);
if (bs->tw_id)
{
TW (tw_timer_update) (&bm->wheel, bs->tw_id, wheel_time_ticks);
BFD_DBG ("tw_timer_update(%p, %u, %lu);", &bm->wheel, bs->tw_id,
wheel_time_ticks);
}
else
{
bs->tw_id =
TW (tw_timer_start) (&bm->wheel, bs->bs_idx, 0, wheel_time_ticks);
BFD_DBG ("tw_timer_start(%p, %u, 0, %lu) == %u;", &bm->wheel,
bs->bs_idx, wheel_time_ticks);
}
if (!handling_wakeup)
{
/* Send only if it is earlier than current awaited wakeup time */
send_signal =
(bs->event_time_nsec < bm->bfd_process_next_wakeup_nsec) &&
/*
* If the wake-up time is within 2x the delay of the event propagation delay,
* avoid the expense of sending the event. The 2x multiplier is to workaround the race whereby
* simultaneous event + expired timer create one recurring bogus wakeup/suspend instance,
* due to double scheduling of the node on the pending list.
*/
(bm->bfd_process_next_wakeup_nsec - bs->event_time_nsec >
2 * bm->bfd_process_wakeup_event_delay_nsec) &&
/* Must be no events in flight to send an event */
(!bm->bfd_process_wakeup_events_in_flight);
/* If we do send the signal, note this down along with the start timestamp */
if (send_signal)
{
bm->bfd_process_wakeup_events_in_flight++;
bm->bfd_process_wakeup_event_start_nsec = now;
}
}
bfd_unlock (bm);
/* Use the multithreaded event sending so the workers can send events too */
if (send_signal)
{
vlib_process_signal_event_mt (bm->vlib_main,
bm->bfd_process_node_index,
BFD_EVENT_RESCHEDULE, ~0);
}
}
}
static void
bfd_set_effective_desired_min_tx (bfd_main_t * bm,
bfd_session_t * bs, u64 now,
u64 desired_min_tx_nsec)
{
bs->effective_desired_min_tx_nsec = desired_min_tx_nsec;
BFD_DBG ("Set effective desired min tx to " BFD_CLK_FMT,
BFD_CLK_PRN (bs->effective_desired_min_tx_nsec));
bfd_recalc_detection_time (bm, bs);
bfd_recalc_tx_interval (bm, bs);
bfd_recalc_echo_tx_interval (bm, bs);
bfd_calc_next_tx (bm, bs, now);
}
static void
bfd_set_effective_required_min_rx (bfd_main_t * bm,
bfd_session_t * bs,
u64 required_min_rx_nsec)
{
bs->effective_required_min_rx_nsec = required_min_rx_nsec;
BFD_DBG ("Set effective required min rx to " BFD_CLK_FMT,
BFD_CLK_PRN (bs->effective_required_min_rx_nsec));
bfd_recalc_detection_time (bm, bs);
}
static void
bfd_set_remote_required_min_rx (bfd_main_t * bm, bfd_session_t * bs,
u64 now, u32 remote_required_min_rx_usec)
{
if (bs->remote_min_rx_usec != remote_required_min_rx_usec)
{
bs->remote_min_rx_usec = remote_required_min_rx_usec;
bs->remote_min_rx_nsec = bfd_usec_to_nsec (remote_required_min_rx_usec);
BFD_DBG ("Set remote min rx to " BFD_CLK_FMT,
BFD_CLK_PRN (bs->remote_min_rx_nsec));
bfd_recalc_detection_time (bm, bs);
bfd_recalc_tx_interval (bm, bs);
}
}
static void
bfd_set_remote_required_min_echo_rx (bfd_main_t * bm, bfd_session_t * bs,
u64 now,
u32 remote_required_min_echo_rx_usec)
{
if (bs->remote_min_echo_rx_usec != remote_required_min_echo_rx_usec)
{
bs->remote_min_echo_rx_usec = remote_required_min_echo_rx_usec;
bs->remote_min_echo_rx_nsec =
bfd_usec_to_nsec (bs->remote_min_echo_rx_usec);
BFD_DBG ("Set remote min echo rx to " BFD_CLK_FMT,
BFD_CLK_PRN (bs->remote_min_echo_rx_nsec));
bfd_recalc_echo_tx_interval (bm, bs);
}
}
static void
bfd_notify_listeners (bfd_main_t * bm,
bfd_listen_event_e event, const bfd_session_t * bs)
{
bfd_notify_fn_t *fn;
vec_foreach (fn, bm->listeners)
{
(*fn) (event, bs);
}
}
void
bfd_session_start (bfd_main_t * bm, bfd_session_t * bs)
{
BFD_DBG ("\nStarting session: %U", format_bfd_session, bs);
vlib_log_info (bm->log_class, "start BFD session: %U",
format_bfd_session_brief, bs);
bfd_set_effective_required_min_rx (bm, bs, bs->config_required_min_rx_nsec);
bfd_recalc_tx_interval (bm, bs);
vlib_process_signal_event (bm->vlib_main, bm->bfd_process_node_index,
BFD_EVENT_NEW_SESSION, bs->bs_idx);
bfd_notify_listeners (bm, BFD_LISTEN_EVENT_CREATE, bs);
}
void
bfd_session_set_flags (vlib_main_t * vm, bfd_session_t * bs, u8 admin_up_down)
{
bfd_main_t *bm = &bfd_main;
u64 now = bfd_time_now_nsec (vm, NULL);
if (admin_up_down)
{
BFD_DBG ("Session set admin-up, bs-idx=%u", bs->bs_idx);
vlib_log_info (bm->log_class, "set session admin-up: %U",
format_bfd_session_brief, bs);
bfd_set_state (vm, bm, bs, BFD_STATE_down, 0);
bfd_set_diag (bs, BFD_DIAG_CODE_no_diag);
bfd_calc_next_tx (bm, bs, now);
bfd_set_timer (bm, bs, now, 0);
}
else
{
BFD_DBG ("Session set admin-down, bs-idx=%u", bs->bs_idx);
vlib_log_info (bm->log_class, "set session admin-down: %U",
format_bfd_session_brief, bs);
bfd_set_diag (bs, BFD_DIAG_CODE_admin_down);
bfd_set_state (vm, bm, bs, BFD_STATE_admin_down, 0);
bfd_calc_next_tx (bm, bs, now);
bfd_set_timer (bm, bs, now, 0);
}
}
u8 *
bfd_input_format_trace (u8 * s, va_list * args)
{
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
const bfd_input_trace_t *t = va_arg (*args, bfd_input_trace_t *);
const bfd_pkt_t *pkt = (bfd_pkt_t *) t->data;
if (t->len > STRUCT_SIZE_OF (bfd_pkt_t, head))
{
s = format (s, "BFD v%u, diag=%u(%s), state=%u(%s),\n"
" flags=(P:%u, F:%u, C:%u, A:%u, D:%u, M:%u), "
"detect_mult=%u, length=%u\n",
bfd_pkt_get_version (pkt), bfd_pkt_get_diag_code (pkt),
bfd_diag_code_string (bfd_pkt_get_diag_code (pkt)),
bfd_pkt_get_state (pkt),
bfd_state_string (bfd_pkt_get_state (pkt)),
bfd_pkt_get_poll (pkt), bfd_pkt_get_final (pkt),
bfd_pkt_get_control_plane_independent (pkt),
bfd_pkt_get_auth_present (pkt), bfd_pkt_get_demand (pkt),
bfd_pkt_get_multipoint (pkt), pkt->head.detect_mult,
pkt->head.length);
if (t->len >= sizeof (bfd_pkt_t) &&
pkt->head.length >= sizeof (bfd_pkt_t))
{
s = format (s, " my discriminator: %u\n",
clib_net_to_host_u32 (pkt->my_disc));
s = format (s, " your discriminator: %u\n",
clib_net_to_host_u32 (pkt->your_disc));
s = format (s, " desired min tx interval: %u\n",
clib_net_to_host_u32 (pkt->des_min_tx));
s = format (s, " required min rx interval: %u\n",
clib_net_to_host_u32 (pkt->req_min_rx));
s = format (s, " required min echo rx interval: %u",
clib_net_to_host_u32 (pkt->req_min_echo_rx));
}
if (t->len >= sizeof (bfd_pkt_with_common_auth_t) &&
pkt->head.length >= sizeof (bfd_pkt_with_common_auth_t) &&
bfd_pkt_get_auth_present (pkt))
{
const bfd_pkt_with_common_auth_t *with_auth = (void *) pkt;
const bfd_auth_common_t *common = &with_auth->common_auth;
s = format (s, "\n auth len: %u\n", common->len);
s = format (s, " auth type: %u:%s\n", common->type,
bfd_auth_type_str (common->type));
if (t->len >= sizeof (bfd_pkt_with_sha1_auth_t) &&
pkt->head.length >= sizeof (bfd_pkt_with_sha1_auth_t) &&
(BFD_AUTH_TYPE_keyed_sha1 == common->type ||
BFD_AUTH_TYPE_meticulous_keyed_sha1 == common->type))
{
const bfd_pkt_with_sha1_auth_t *with_sha1 = (void *) pkt;
const bfd_auth_sha1_t *sha1 = &with_sha1->sha1_auth;
s = format (s, " seq num: %u\n",
clib_net_to_host_u32 (sha1->seq_num));
s = format (s, " key id: %u\n", sha1->key_id);
s = format (s, " hash: %U", format_hex_bytes, sha1->hash,
sizeof (sha1->hash));
}
}
else
{
s = format (s, "\n");
}
}
return s;
}
typedef struct
{
u32 bs_idx;
} bfd_rpc_event_t;
static void
bfd_rpc_event_cb (const bfd_rpc_event_t * a)
{
bfd_main_t *bm = &bfd_main;
u32 bs_idx = a->bs_idx;
u32 valid_bs = 0;
bfd_session_t session_data;
bfd_lock (bm);
if (!pool_is_free_index (bm->sessions, bs_idx))
{
bfd_session_t *bs = pool_elt_at_index (bm->sessions, bs_idx);
clib_memcpy (&session_data, bs, sizeof (bfd_session_t));
valid_bs = 1;
}
else
{
BFD_DBG ("Ignoring event RPC for non-existent session index %u",
bs_idx);
}
bfd_unlock (bm);
if (valid_bs)
bfd_event (bm, &session_data);
}
static void
bfd_event_rpc (u32 bs_idx)
{
const u32 data_size = sizeof (bfd_rpc_event_t);
u8 data[data_size];
bfd_rpc_event_t *event = (bfd_rpc_event_t *) data;
event->bs_idx = bs_idx;
vl_api_rpc_call_main_thread (bfd_rpc_event_cb, data, data_size);
}
typedef struct
{
u32 bs_idx;
} bfd_rpc_notify_listeners_t;
static void
bfd_rpc_notify_listeners_cb (const bfd_rpc_notify_listeners_t * a)
{
bfd_main_t *bm = &bfd_main;
u32 bs_idx = a->bs_idx;
bfd_lock (bm);
if (!pool_is_free_index (bm->sessions, bs_idx))
{
bfd_session_t *bs = pool_elt_at_index (bm->sessions, bs_idx);
bfd_notify_listeners (bm, BFD_LISTEN_EVENT_UPDATE, bs);
}
else
{
BFD_DBG ("Ignoring notify RPC for non-existent session index %u",
bs_idx);
}
bfd_unlock (bm);
}
static void
bfd_notify_listeners_rpc (u32 bs_idx)
{
const u32 data_size = sizeof (bfd_rpc_notify_listeners_t);
u8 data[data_size];
bfd_rpc_notify_listeners_t *notify = (bfd_rpc_notify_listeners_t *) data;
notify->bs_idx = bs_idx;
vl_api_rpc_call_main_thread (bfd_rpc_notify_listeners_cb, data, data_size);
}
static void
bfd_on_state_change (bfd_main_t * bm, bfd_session_t * bs, u64 now,
int handling_wakeup)
{
BFD_DBG ("\nState changed: %U", format_bfd_session, bs);
if (vlib_get_thread_index () == 0)
{
bfd_event (bm, bs);
}
else
{
/* without RPC - a REGRESSION: BFD event are not propagated */
bfd_event_rpc (bs->bs_idx);
}
switch (bs->local_state)
{
case BFD_STATE_admin_down:
bs->echo = 0;
bfd_set_effective_desired_min_tx (bm, bs, now,
clib_max
(bs->config_desired_min_tx_nsec,
bm->default_desired_min_tx_nsec));
bfd_set_effective_required_min_rx (bm, bs,
bs->config_required_min_rx_nsec);
bfd_set_timer (bm, bs, now, handling_wakeup);
break;
case BFD_STATE_down:
bs->echo = 0;
bfd_set_effective_desired_min_tx (bm, bs, now,
clib_max
(bs->config_desired_min_tx_nsec,
bm->default_desired_min_tx_nsec));
bfd_set_effective_required_min_rx (bm, bs,
bs->config_required_min_rx_nsec);
bfd_set_timer (bm, bs, now, handling_wakeup);
break;
case BFD_STATE_init:
bs->echo = 0;
bfd_set_effective_desired_min_tx (bm, bs, now,
bs->config_desired_min_tx_nsec);
bfd_set_timer (bm, bs, now, handling_wakeup);
break;
case BFD_STATE_up:
bfd_set_effective_desired_min_tx (bm, bs, now,
bs->config_desired_min_tx_nsec);
if (BFD_POLL_NOT_NEEDED == bs->poll_state)
{
bfd_set_effective_required_min_rx (bm, bs,
bs->config_required_min_rx_nsec);
}
bfd_set_timer (bm, bs, now, handling_wakeup);
break;
}
if (vlib_get_thread_index () == 0)
{
bfd_notify_listeners (bm, BFD_LISTEN_EVENT_UPDATE, bs);
}
else
{
/* without RPC - a REGRESSION: state changes are not propagated */
bfd_notify_listeners_rpc (bs->bs_idx);
}
}
static void
bfd_on_config_change (vlib_main_t * vm, vlib_node_runtime_t * rt,
bfd_main_t * bm, bfd_session_t * bs, u64 now)
{
/*
* if remote demand mode is set and we need to do a poll, set the next
* timeout so that the session wakes up immediately
*/
if (bs->remote_demand && BFD_POLL_NEEDED == bs->poll_state &&
bs->poll_state_start_or_timeout_nsec < now)
{
bs->tx_timeout_nsec = now;
}
bfd_recalc_detection_time (bm, bs);
bfd_set_timer (bm, bs, now, 0);
}
static void
bfd_add_transport_layer (vlib_main_t * vm, u32 bi, bfd_session_t * bs)
{
switch (bs->transport)
{
case BFD_TRANSPORT_UDP4:
BFD_DBG ("Transport bfd via udp4, bs_idx=%u", bs->bs_idx);
bfd_add_udp4_transport (vm, bi, bs, 0 /* is_echo */ );
break;
case BFD_TRANSPORT_UDP6:
BFD_DBG ("Transport bfd via udp6, bs_idx=%u", bs->bs_idx);
bfd_add_udp6_transport (vm, bi, bs, 0 /* is_echo */ );
break;
}
}
static int
bfd_transport_control_frame (vlib_main_t * vm, u32 bi, bfd_session_t * bs)
{
switch (bs->transport)
{
case BFD_TRANSPORT_UDP4:
BFD_DBG ("Transport bfd via udp4, bs_idx=%u", bs->bs_idx);
return bfd_transport_udp4 (vm, bi, bs);
break;
case BFD_TRANSPORT_UDP6:
BFD_DBG ("Transport bfd via udp6, bs_idx=%u", bs->bs_idx);
return bfd_transport_udp6 (vm, bi, bs);
break;
}
return 0;
}
static int
bfd_echo_add_transport_layer (vlib_main_t * vm, u32 bi, bfd_session_t * bs)
{
switch (bs->transport)
{
case BFD_TRANSPORT_UDP4:
BFD_DBG ("Transport bfd echo via udp4, bs_idx=%u", bs->bs_idx);
return bfd_add_udp4_transport (vm, bi, bs, 1 /* is_echo */ );
break;
case BFD_TRANSPORT_UDP6:
BFD_DBG ("Transport bfd echo via udp6, bs_idx=%u", bs->bs_idx);
return bfd_add_udp6_transport (vm, bi, bs, 1 /* is_echo */ );
break;
}
return 0;
}
static int
bfd_transport_echo (vlib_main_t * vm, u32 bi, bfd_session_t * bs)
{
switch (bs->transport)
{
case BFD_TRANSPORT_UDP4:
BFD_DBG ("Transport bfd echo via udp4, bs_idx=%u", bs->bs_idx);
return bfd_transport_udp4 (vm, bi, bs);
break;
case BFD_TRANSPORT_UDP6:
BFD_DBG ("Transport bfd echo via udp6, bs_idx=%u", bs->bs_idx);
return bfd_transport_udp6 (vm, bi, bs);
break;
}
return 0;
}
#if WITH_LIBSSL > 0
static void
bfd_add_sha1_auth_section (vlib_buffer_t * b, bfd_session_t * bs)
{
bfd_pkt_with_sha1_auth_t *pkt = vlib_buffer_get_current (b);
bfd_auth_sha1_t *auth = &pkt->sha1_auth;
b->current_length += sizeof (*auth);
pkt->pkt.head.length += sizeof (*auth);
bfd_pkt_set_auth_present (&pkt->pkt);
clib_memset (auth, 0, sizeof (*auth));
auth->type_len.type = bs->auth.curr_key->auth_type;
/*
* only meticulous authentication types require incrementing seq number
* for every message, but doing so doesn't violate the RFC
*/
++bs->auth.local_seq_number;
auth->type_len.len = sizeof (bfd_auth_sha1_t);
auth->key_id = bs->auth.curr_bfd_key_id;
auth->seq_num = clib_host_to_net_u32 (bs->auth.local_seq_number);
/*
* first copy the password into the packet, then calculate the hash
* and finally replace the password with the calculated hash
*/
clib_memcpy (auth->hash, bs->auth.curr_key->key,
sizeof (bs->auth.curr_key->key));
unsigned char hash[sizeof (auth->hash)];
SHA1 ((unsigned char *) pkt, sizeof (*pkt), hash);
BFD_DBG ("hashing: %U", format_hex_bytes, pkt, sizeof (*pkt));
clib_memcpy (auth->hash, hash, sizeof (hash));
}
#endif
static void
bfd_add_auth_section (vlib_buffer_t * b, bfd_session_t * bs)
{
bfd_main_t *bm = &bfd_main;
if (bs->auth.curr_key)
{
const bfd_auth_type_e auth_type = bs->auth.curr_key->auth_type;
switch (auth_type)
{
case BFD_AUTH_TYPE_reserved:
/* fallthrough */
case BFD_AUTH_TYPE_simple_password:
/* fallthrough */
case BFD_AUTH_TYPE_keyed_md5:
/* fallthrough */
case BFD_AUTH_TYPE_meticulous_keyed_md5:
vlib_log_crit (bm->log_class,
"internal error, unexpected BFD auth type '%d'",
auth_type);
break;
#if WITH_LIBSSL > 0
case BFD_AUTH_TYPE_keyed_sha1:
/* fallthrough */
case BFD_AUTH_TYPE_meticulous_keyed_sha1:
bfd_add_sha1_auth_section (b, bs);
break;
#else
case BFD_AUTH_TYPE_keyed_sha1:
/* fallthrough */
case BFD_AUTH_TYPE_meticulous_keyed_sha1:
vlib_log_crit (bm->log_class,
"internal error, unexpected BFD auth type '%d'",
auth_type);
break;
#endif
}
}
}
static int
bfd_is_echo_possible (bfd_session_t * bs)
{
if (BFD_STATE_up == bs->local_state && BFD_STATE_up == bs->remote_state &&
bs->remote_min_echo_rx_usec > 0)
{
switch (bs->transport)
{
case BFD_TRANSPORT_UDP4:
return bfd_udp_is_echo_available (BFD_TRANSPORT_UDP4);
case BFD_TRANSPORT_UDP6:
return bfd_udp_is_echo_available (BFD_TRANSPORT_UDP6);
}
}
return 0;
}
static void
bfd_init_control_frame (bfd_main_t * bm, bfd_session_t * bs,
vlib_buffer_t * b)
{
bfd_pkt_t *pkt = vlib_buffer_get_current (b);
u32 bfd_length = 0;
bfd_length = sizeof (bfd_pkt_t);
clib_memset (pkt, 0, sizeof (*pkt));
bfd_pkt_set_version (pkt, 1);
bfd_pkt_set_diag_code (pkt, bs->local_diag);
bfd_pkt_set_state (pkt, bs->local_state);
pkt->head.detect_mult = bs->local_detect_mult;
pkt->head.length = bfd_length;
pkt->my_disc = bs->local_discr;
pkt->your_disc = bs->remote_discr;
pkt->des_min_tx = clib_host_to_net_u32 (bs->config_desired_min_tx_usec);
if (bs->echo)
{
pkt->req_min_rx =
clib_host_to_net_u32 (bfd_nsec_to_usec
(bs->effective_required_min_rx_nsec));
}
else
{
pkt->req_min_rx =
clib_host_to_net_u32 (bs->config_required_min_rx_usec);
}
pkt->req_min_echo_rx = clib_host_to_net_u32 (1);
b->current_length = bfd_length;
}
static void
bfd_send_echo (vlib_main_t * vm, vlib_node_runtime_t * rt,
bfd_main_t * bm, bfd_session_t * bs, u64 now)
{
if (!bfd_is_echo_possible (bs))
{
BFD_DBG ("\nSwitching off echo function: %U", format_bfd_session, bs);
bs->echo = 0;
return;
}
if (now >= bs->echo_tx_timeout_nsec)
{
BFD_DBG ("\nSending echo packet: %U", format_bfd_session, bs);
u32 bi;
if (vlib_buffer_alloc (vm, &bi, 1) != 1)
{
vlib_log_crit (bm->log_class, "buffer allocation failure");
return;
}
vlib_buffer_t *b = vlib_get_buffer (vm, bi);
ASSERT (b->current_data == 0);
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b);
bfd_echo_pkt_t *pkt = vlib_buffer_get_current (b);
clib_memset (pkt, 0, sizeof (*pkt));
pkt->discriminator = bs->local_discr;
pkt->expire_time_nsec =
now + bs->echo_transmit_interval_nsec * bs->local_detect_mult;
pkt->checksum =
bfd_calc_echo_checksum (bs->local_discr, pkt->expire_time_nsec,
bs->echo_secret);
b->current_length = sizeof (*pkt);
if (!bfd_echo_add_transport_layer (vm, bi, bs))
{
BFD_ERR ("cannot send echo packet out, turning echo off");
bs->echo = 0;
vlib_buffer_free_one (vm, bi);
return;
}
if (!bfd_transport_echo (vm, bi, bs))
{
BFD_ERR ("cannot send echo packet out, turning echo off");
bs->echo = 0;
vlib_buffer_free_one (vm, bi);
return;
}
bs->echo_last_tx_nsec = now;
bfd_calc_next_echo_tx (bm, bs, now);
}
else
{
BFD_DBG
("No need to send echo packet now, now is %lu, tx_timeout is %lu",
now, bs->echo_tx_timeout_nsec);
}
}
static void
bfd_send_periodic (vlib_main_t * vm, vlib_node_runtime_t * rt,
bfd_main_t * bm, bfd_session_t * bs, u64 now)
{
if (!bs->remote_min_rx_usec && BFD_POLL_NOT_NEEDED == bs->poll_state)
{
BFD_DBG ("Remote min rx interval is zero, not sending periodic control "
"frame");
return;
}
if (BFD_POLL_NOT_NEEDED == bs->poll_state && bs->remote_demand &&
BFD_STATE_up == bs->local_state && BFD_STATE_up == bs->remote_state)
{
/*
* A system MUST NOT periodically transmit BFD Control packets if Demand
* mode is active on the remote system (bfd.RemoteDemandMode is 1,
* bfd.SessionState is Up, and bfd.RemoteSessionState is Up) and a Poll
* Sequence is not being transmitted.
*/
BFD_DBG ("Remote demand is set, not sending periodic control frame");
return;
}
if (now >= bs->tx_timeout_nsec)
{
BFD_DBG ("\nSending periodic control frame: %U", format_bfd_session,
bs);
u32 bi;
if (vlib_buffer_alloc (vm, &bi, 1) != 1)
{
vlib_log_crit (bm->log_class, "buffer allocation failure");
return;
}
vlib_buffer_t *b = vlib_get_buffer (vm, bi);
ASSERT (b->current_data == 0);
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b);
bfd_init_control_frame (bm, bs, b);
switch (bs->poll_state)
{
case BFD_POLL_NEEDED:
if (now < bs->poll_state_start_or_timeout_nsec)
{
BFD_DBG ("Cannot start a poll sequence yet, need to wait for "
BFD_CLK_FMT,
BFD_CLK_PRN (bs->poll_state_start_or_timeout_nsec -
now));
break;
}
bs->poll_state_start_or_timeout_nsec = now;
bfd_set_poll_state (bs, BFD_POLL_IN_PROGRESS);
/* fallthrough */
case BFD_POLL_IN_PROGRESS:
case BFD_POLL_IN_PROGRESS_AND_QUEUED:
bfd_pkt_set_poll (vlib_buffer_get_current (b));
BFD_DBG ("Setting poll bit in packet, bs_idx=%u", bs->bs_idx);
break;
case BFD_POLL_NOT_NEEDED:
/* fallthrough */
break;
}
bfd_add_auth_section (b, bs);
bfd_add_transport_layer (vm, bi, bs);
if (!bfd_transport_control_frame (vm, bi, bs))
{
vlib_buffer_free_one (vm, bi);
}
bs->last_tx_nsec = now;
bfd_calc_next_tx (bm, bs, now);
}
else
{
BFD_DBG
("No need to send control frame now, now is %lu, tx_timeout is %lu",
now, bs->tx_timeout_nsec);
}
}
void
bfd_init_final_control_frame (vlib_main_t * vm, vlib_buffer_t * b,
bfd_main_t * bm, bfd_session_t * bs,
int is_local)
{
BFD_DBG ("Send final control frame for bs_idx=%lu", bs->bs_idx);
bfd_init_control_frame (bm, bs, b);
bfd_pkt_set_final (vlib_buffer_get_current (b));
bfd_add_auth_section (b, bs);
u32 bi = vlib_get_buffer_index (vm, b);
bfd_add_transport_layer (vm, bi, bs);
bs->last_tx_nsec = bfd_time_now_nsec (vm, NULL);
/*
* RFC allows to include changes in final frame, so if there were any
* pending, we already did that, thus we can clear any pending poll needs
*/
bfd_set_poll_state (bs, BFD_POLL_NOT_NEEDED);
}
static void
bfd_check_rx_timeout (vlib_main_t * vm, bfd_main_t * bm, bfd_session_t * bs,
u64 now, int handling_wakeup)
{
if (bs->last_rx_nsec + bs->detection_time_nsec <= now)
{
BFD_DBG ("Rx timeout, session goes down");
/*
* RFC 5880 6.8.1. State Variables
* bfd.RemoteDiscr
* The remote discriminator for this BFD session. This is the
* discriminator chosen by the remote system, and is totally opaque
* to the local system. This MUST be initialized to zero. If a
* period of a Detection Time passes without the receipt of a valid,
* authenticated BFD packet from the remote system, this variable
* MUST be set to zero.
*/
bs->remote_discr = 0;
bfd_set_diag (bs, BFD_DIAG_CODE_det_time_exp);
bfd_set_state (vm, bm, bs, BFD_STATE_down, handling_wakeup);
/*
* If the remote system does not receive any
* BFD Control packets for a Detection Time, it SHOULD reset
* bfd.RemoteMinRxInterval to its initial value of 1 (per section 6.8.1,
* since it is no longer required to maintain previous session state)
* and then can transmit at its own rate.
*/
bfd_set_remote_required_min_rx (bm, bs, now, 1);
}
else if (bs->echo
&& bs->echo_last_rx_nsec +
bs->echo_transmit_interval_nsec * bs->local_detect_mult <= now)
{
BFD_DBG ("Echo rx timeout, session goes down");
bfd_set_diag (bs, BFD_DIAG_CODE_echo_failed);
bfd_set_state (vm, bm, bs, BFD_STATE_down, handling_wakeup);
}
}
void
bfd_on_timeout (vlib_main_t * vm, vlib_node_runtime_t * rt, bfd_main_t * bm,
bfd_session_t * bs, u64 now)
{
BFD_DBG ("Timeout for bs_idx=%lu", bs->bs_idx);
switch (bs->local_state)
{
case BFD_STATE_admin_down:
bfd_send_periodic (vm, rt, bm, bs, now);
break;
case BFD_STATE_down:
bfd_send_periodic (vm, rt, bm, bs, now);
break;
case BFD_STATE_init:
bfd_check_rx_timeout (vm, bm, bs, now, 1);
bfd_send_periodic (vm, rt, bm, bs, now);
break;
case BFD_STATE_up:
bfd_check_rx_timeout (vm, bm, bs, now, 1);
if (BFD_POLL_NOT_NEEDED == bs->poll_state && !bs->echo &&
bfd_is_echo_possible (bs))
{
/* switch on echo function as main detection method now */
BFD_DBG ("Switching on echo function, bs_idx=%u", bs->bs_idx);
bs->echo = 1;
bs->echo_last_rx_nsec = now;
bs->echo_tx_timeout_nsec = now;
bfd_set_effective_required_min_rx (bm, bs,
clib_max
(bm->min_required_min_rx_while_echo_nsec,
bs->config_required_min_rx_nsec));
bfd_set_poll_state (bs, BFD_POLL_NEEDED);
}
bfd_send_periodic (vm, rt, bm, bs, now);
if (bs->echo)
{
bfd_send_echo (vm, rt, bm, bs, now);
}
break;
}
}
/*
* bfd process node function
*/
static uword
bfd_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
{
bfd_main_t *bm = &bfd_main;
u32 *expired = 0;
uword event_type, *event_data = 0;
/* So we can send events to the bfd process */
bm->bfd_process_node_index = bfd_process_node.index;
while (1)
{
f64 vm_time;
u64 now = bfd_time_now_nsec (vm, &vm_time);
BFD_DBG ("wakeup, now is %llunsec, vlib_time_now() is %.9f", now,
vm_time);
bfd_lock (bm);
f64 timeout;
if (pool_elts (bm->sessions))
{
u32 first_expires_in_ticks =
TW (tw_timer_first_expires_in_ticks) (&bm->wheel);
if (!first_expires_in_ticks)
{
BFD_DBG
("tw_timer_first_expires_in_ticks(%p) returns 0ticks",
&bm->wheel);
timeout = bm->wheel.next_run_time - vm_time;
BFD_DBG ("wheel.next_run_time is %.9f",
bm->wheel.next_run_time);
u64 next_expire_nsec = now + timeout * SEC_PER_NSEC;
bm->bfd_process_next_wakeup_nsec = next_expire_nsec;
bfd_unlock (bm);
}
else
{
BFD_DBG ("tw_timer_first_expires_in_ticks(%p) returns %luticks",
&bm->wheel, first_expires_in_ticks);
u64 next_expire_nsec =
now + first_expires_in_ticks * bm->nsec_per_tw_tick;
bm->bfd_process_next_wakeup_nsec = next_expire_nsec;
bfd_unlock (bm);
timeout = (next_expire_nsec - now) * SEC_PER_NSEC;
}
BFD_DBG ("vlib_process_wait_for_event_or_clock(vm, %.09f)",
timeout);
(void) vlib_process_wait_for_event_or_clock (vm, timeout);
}
else
{
bfd_unlock (bm);
(void) vlib_process_wait_for_event (vm);
}
event_type = vlib_process_get_events (vm, &event_data);
now = bfd_time_now_nsec (vm, &vm_time);
uword *session_index;
switch (event_type)
{
case ~0: /* no events => timeout */
/* nothing to do here */
break;
case BFD_EVENT_RESCHEDULE:
BFD_DBG ("reschedule event");
bfd_lock (bm);
bm->bfd_process_wakeup_event_delay_nsec =
now - bm->bfd_process_wakeup_event_start_nsec;
bm->bfd_process_wakeup_events_in_flight--;
bfd_unlock (bm);
/* nothing to do here - reschedule is done automatically after
* each event or timeout */
break;
case BFD_EVENT_NEW_SESSION:
vec_foreach (session_index, event_data)
{
bfd_lock (bm);
if (!pool_is_free_index (bm->sessions, *session_index))
{
bfd_session_t *bs =
pool_elt_at_index (bm->sessions, *session_index);
bfd_send_periodic (vm, rt, bm, bs, now);
bfd_set_timer (bm, bs, now, 1);
}
else
{
BFD_DBG ("Ignoring event for non-existent session index %u",
(u32) * session_index);
}
bfd_unlock (bm);
}
break;
case BFD_EVENT_CONFIG_CHANGED:
vec_foreach (session_index, event_data)
{
bfd_lock (bm);
if (!pool_is_free_index (bm->sessions, *session_index))
{
bfd_session_t *bs =
pool_elt_at_index (bm->sessions, *session_index);
bfd_on_config_change (vm, rt, bm, bs, now);
}
else
{
BFD_DBG ("Ignoring event for non-existent session index %u",
(u32) * session_index);
}
bfd_unlock (bm);
}
break;
default:
vlib_log_err (bm->log_class, "BUG: event type 0x%wx", event_type);
break;
}
BFD_DBG ("tw_timer_expire_timers_vec(%p, %.04f);", &bm->wheel, vm_time);
bfd_lock (bm);
expired =
TW (tw_timer_expire_timers_vec) (&bm->wheel, vm_time, expired);
BFD_DBG ("Expired %d elements", vec_len (expired));
u32 *p = NULL;
vec_foreach (p, expired)
{
const u32 bs_idx = *p;
if (!pool_is_free_index (bm->sessions, bs_idx))
{
bfd_session_t *bs = pool_elt_at_index (bm->sessions, bs_idx);
bs->tw_id = 0; /* timer is gone because it expired */
bfd_on_timeout (vm, rt, bm, bs, now);
bfd_set_timer (bm, bs, now, 1);
}
}
bfd_unlock (bm);
if (expired)
{
_vec_len (expired) = 0;
}
if (event_data)
{
_vec_len (event_data) = 0;
}
}
return 0;
}
/*
* bfd process node declaration
*/
/* *INDENT-OFF* */
VLIB_REGISTER_NODE (bfd_process_node, static) = {
.function = bfd_process,
.type = VLIB_NODE_TYPE_PROCESS,
.name = "bfd-process",
.n_next_nodes = 0,
.next_nodes = {},
};
/* *INDENT-ON* */
static clib_error_t *
bfd_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
{
// bfd_main_t *bm = &bfd_main;
// vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
{
/* TODO */
}
return 0;
}
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (bfd_sw_interface_up_down);
static clib_error_t *
bfd_hw_interface_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
{
// bfd_main_t *bm = &bfd_main;
if (flags & VNET_HW_INTERFACE_FLAG_LINK_UP)
{
/* TODO */
}
return 0;
}
VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (bfd_hw_interface_up_down);
void
bfd_register_listener (bfd_notify_fn_t fn)
{
bfd_main_t *bm = &bfd_main;
vec_add1 (bm->listeners, fn);
}
/*
* setup function
*/
static clib_error_t *
bfd_main_init (vlib_main_t * vm)
{
vlib_thread_main_t *tm = &vlib_thread_main;
u32 n_vlib_mains = tm->n_vlib_mains;
#if BFD_DEBUG
setbuf (stdout, NULL);
#endif
bfd_main_t *bm = &bfd_main;
bm->random_seed = random_default_seed ();
bm->vlib_main = vm;
bm->vnet_main = vnet_get_main ();
clib_memset (&bm->wheel, 0, sizeof (bm->wheel));
bm->nsec_per_tw_tick = (f64) NSEC_PER_SEC / BFD_TW_TPS;
bm->default_desired_min_tx_nsec =
bfd_usec_to_nsec (BFD_DEFAULT_DESIRED_MIN_TX_USEC);
bm->min_required_min_rx_while_echo_nsec =
bfd_usec_to_nsec (BFD_REQUIRED_MIN_RX_USEC_WHILE_ECHO);
BFD_DBG ("tw_timer_wheel_init(%p, %p, %.04f, %u)", &bm->wheel, NULL,
1.00 / BFD_TW_TPS, ~0);
TW (tw_timer_wheel_init) (&bm->wheel, NULL, 1.00 / BFD_TW_TPS, ~0);
bm->log_class = vlib_log_register_class ("bfd", 0);
vlib_log_debug (bm->log_class, "initialized");
bm->owner_thread_index = ~0;
if (n_vlib_mains > 1)
clib_spinlock_init (&bm->lock);
return 0;
}
VLIB_INIT_FUNCTION (bfd_main_init);
bfd_session_t *
bfd_get_session (bfd_main_t * bm, bfd_transport_e t)
{
bfd_session_t *result;
bfd_lock (bm);
pool_get (bm->sessions, result);
clib_memset (result, 0, sizeof (*result));
result->bs_idx = result - bm->sessions;
result->transport = t;
const unsigned limit = 1000;
unsigned counter = 0;
do
{
result->local_discr = random_u32 (&bm->random_seed);
if (counter > limit)
{
vlib_log_crit (bm->log_class,
"couldn't allocate unused session discriminator even "
"after %u tries!", limit);
pool_put (bm->sessions, result);
bfd_unlock (bm);
return NULL;
}
++counter;
}
while (hash_get (bm->session_by_disc, result->local_discr));
bfd_set_defaults (bm, result);
hash_set (bm->session_by_disc, result->local_discr, result->bs_idx);
bfd_unlock (bm);
return result;
}
void
bfd_put_session (bfd_main_t * bm, bfd_session_t * bs)
{
bfd_lock (bm);
vlib_log_info (bm->log_class, "delete session: %U",
format_bfd_session_brief, bs);
bfd_notify_listeners (bm, BFD_LISTEN_EVENT_DELETE, bs);
if (bs->auth.curr_key)
{
--bs->auth.curr_key->use_count;
}
if (bs->auth.next_key)
{
--bs->auth.next_key->use_count;
}
hash_unset (bm->session_by_disc, bs->local_discr);
pool_put (bm->sessions, bs);
bfd_unlock (bm);
}
bfd_session_t *
bfd_find_session_by_idx (bfd_main_t * bm, uword bs_idx)
{
bfd_lock_check (bm);
if (!pool_is_free_index (bm->sessions, bs_idx))
{
return pool_elt_at_index (bm->sessions, bs_idx);
}
return NULL;
}
bfd_session_t *
bfd_find_session_by_disc (bfd_main_t * bm, u32 disc)
{
bfd_lock_check (bm);
uword *p = hash_get (bfd_main.session_by_disc, disc);
if (p)
{
return pool_elt_at_index (bfd_main.sessions, *p);
}
return NULL;
}
/**
* @brief verify bfd packet - common checks
*
* @param pkt
*
* @return 1 if bfd packet is valid
*/
int
bfd_verify_pkt_common (const bfd_pkt_t * pkt)
{
if (1 != bfd_pkt_get_version (pkt))
{
BFD_ERR ("BFD verification failed - unexpected version: '%d'",
bfd_pkt_get_version (pkt));
return 0;
}
if (pkt->head.length < sizeof (bfd_pkt_t) ||
(bfd_pkt_get_auth_present (pkt) &&
pkt->head.length < sizeof (bfd_pkt_with_common_auth_t)))
{
BFD_ERR ("BFD verification failed - unexpected length: '%d' (auth "
"present: %d)",
pkt->head.length, bfd_pkt_get_auth_present (pkt));
return 0;
}
if (!pkt->head.detect_mult)
{
BFD_ERR ("BFD verification failed - unexpected detect-mult: '%d'",
pkt->head.detect_mult);
return 0;
}
if (bfd_pkt_get_multipoint (pkt))
{
BFD_ERR ("BFD verification failed - unexpected multipoint: '%d'",
bfd_pkt_get_multipoint (pkt));
return 0;
}
if (!pkt->my_disc)
{
BFD_ERR ("BFD verification failed - unexpected my-disc: '%d'",
pkt->my_disc);
return 0;
}
if (!pkt->your_disc)
{
const u8 pkt_state = bfd_pkt_get_state (pkt);
if (pkt_state != BFD_STATE_down && pkt_state != BFD_STATE_admin_down)
{
BFD_ERR ("BFD verification failed - unexpected state: '%s' "
"(your-disc is zero)", bfd_state_string (pkt_state));
return 0;
}
}
return 1;
}
static void
bfd_session_switch_auth_to_next (bfd_session_t * bs)
{
BFD_DBG ("Switching authentication key from %U to %U for bs_idx=%u",
format_bfd_auth_key, bs->auth.curr_key, format_bfd_auth_key,
bs->auth.next_key, bs->bs_idx);
bs->auth.is_delayed = 0;
if (bs->auth.curr_key)
{
--bs->auth.curr_key->use_count;
}
bs->auth.curr_key = bs->auth.next_key;
bs->auth.next_key = NULL;
bs->auth.curr_bfd_key_id = bs->auth.next_bfd_key_id;
}
static int
bfd_auth_type_is_meticulous (bfd_auth_type_e auth_type)
{
if (BFD_AUTH_TYPE_meticulous_keyed_md5 == auth_type ||
BFD_AUTH_TYPE_meticulous_keyed_sha1 == auth_type)
{
return 1;
}
return 0;
}
static int
bfd_verify_pkt_auth_seq_num (vlib_main_t * vm, bfd_session_t * bs,
u32 received_seq_num, int is_meticulous)
{
/*
* RFC 5880 6.8.1:
*
* This variable MUST be set to zero after no packets have been
* received on this session for at least twice the Detection Time.
*/
u64 now = bfd_time_now_nsec (vm, NULL);
if (now - bs->last_rx_nsec > bs->detection_time_nsec * 2)
{
BFD_DBG ("BFD peer unresponsive for %lu nsec, which is > 2 * "
"detection_time=%u nsec, resetting remote_seq_number_known "
"flag", now - bs->last_rx_nsec, bs->detection_time_nsec * 2);
bs->auth.remote_seq_number_known = 0;
}
if (bs->auth.remote_seq_number_known)
{
/* remote sequence number is known, verify its validity */
const u32 max_u32 = 0xffffffff;
/* the calculation might wrap, account for the special case... */
if (bs->auth.remote_seq_number > max_u32 - 3 * bs->local_detect_mult)
{
/*
* special case
*
* x y z
* |----------+----------------------------+-----------|
* 0 ^ ^ 0xffffffff
* | remote_seq_num------+
* |
* +-----(remote_seq_num + 3*detect_mult) % * 0xffffffff
*
* x + y + z = 0xffffffff
* x + z = 3 * detect_mult
*/
const u32 z = max_u32 - bs->auth.remote_seq_number;
const u32 x = 3 * bs->local_detect_mult - z;
if (received_seq_num > x &&
received_seq_num < bs->auth.remote_seq_number + is_meticulous)
{
BFD_ERR
("Recvd sequence number=%u out of ranges <0, %u>, <%u, %u>",
received_seq_num, x,
bs->auth.remote_seq_number + is_meticulous, max_u32);
return 0;
}
}
else
{
/* regular case */
const u32 min = bs->auth.remote_seq_number + is_meticulous;
const u32 max =
bs->auth.remote_seq_number + 3 * bs->local_detect_mult;
if (received_seq_num < min || received_seq_num > max)
{
BFD_ERR ("Recvd sequence number=%u out of range <%u, %u>",
received_seq_num, min, max);
return 0;
}
}
}
return 1;
}
static int
bfd_verify_pkt_auth_key_sha1 (const bfd_pkt_t * pkt, u32 pkt_size,
bfd_session_t * bs, u8 bfd_key_id,
bfd_auth_key_t * auth_key)
{
ASSERT (auth_key->auth_type == BFD_AUTH_TYPE_keyed_sha1 ||
auth_key->auth_type == BFD_AUTH_TYPE_meticulous_keyed_sha1);
u8 result[SHA_DIGEST_LENGTH];
bfd_pkt_with_common_auth_t *with_common = (void *) pkt;
if (pkt_size < sizeof (*with_common))
{
BFD_ERR ("Packet size too small to hold authentication common header");
return 0;
}
if (with_common->common_auth.type != auth_key->auth_type)
{
BFD_ERR ("BFD auth type mismatch, packet auth=%d:%s doesn't match "
"in-use auth=%d:%s",
with_common->common_auth.type,
bfd_auth_type_str (with_common->common_auth.type),
auth_key->auth_type, bfd_auth_type_str (auth_key->auth_type));
return 0;
}
bfd_pkt_with_sha1_auth_t *with_sha1 = (void *) pkt;
if (pkt_size < sizeof (*with_sha1) ||
with_sha1->sha1_auth.type_len.len < sizeof (with_sha1->sha1_auth))
{
BFD_ERR
("BFD size mismatch, payload size=%u, expected=%u, auth_len=%u, "
"expected=%u", pkt_size, sizeof (*with_sha1),
with_sha1->sha1_auth.type_len.len, sizeof (with_sha1->sha1_auth));
return 0;
}
if (with_sha1->sha1_auth.key_id != bfd_key_id)
{
BFD_ERR
("BFD key ID mismatch, packet key ID=%u doesn't match key ID=%u%s",
with_sha1->sha1_auth.key_id, bfd_key_id,
bs->
auth.is_delayed ? " (but a delayed auth change is scheduled)" : "");
return 0;
}
SHA_CTX ctx;
if (!SHA1_Init (&ctx))
{
BFD_ERR ("SHA1_Init failed");
return 0;
}
/* ignore last 20 bytes - use the actual key data instead pkt data */
if (!SHA1_Update (&ctx, with_sha1,
sizeof (*with_sha1) - sizeof (with_sha1->sha1_auth.hash)))
{
BFD_ERR ("SHA1_Update failed");
return 0;
}
if (!SHA1_Update (&ctx, auth_key->key, sizeof (auth_key->key)))
{
BFD_ERR ("SHA1_Update failed");
return 0;
}
if (!SHA1_Final (result, &ctx))
{
BFD_ERR ("SHA1_Final failed");
return 0;
}
if (0 == memcmp (result, with_sha1->sha1_auth.hash, SHA_DIGEST_LENGTH))
{
return 1;
}
BFD_ERR ("SHA1 hash: %U doesn't match the expected value: %U",
format_hex_bytes, with_sha1->sha1_auth.hash, SHA_DIGEST_LENGTH,
format_hex_bytes, result, SHA_DIGEST_LENGTH);
return 0;
}
static int
bfd_verify_pkt_auth_key (vlib_main_t * vm, const bfd_pkt_t * pkt,
u32 pkt_size, bfd_session_t * bs, u8 bfd_key_id,
bfd_auth_key_t * auth_key)
{
bfd_main_t *bm = &bfd_main;
switch (auth_key->auth_type)
{
case BFD_AUTH_TYPE_reserved:
vlib_log_err (bm->log_class,
"internal error, unexpected auth_type=%d:%s",
auth_key->auth_type,
bfd_auth_type_str (auth_key->auth_type));
return 0;
case BFD_AUTH_TYPE_simple_password:
vlib_log_err (bm->log_class,
"internal error, not implemented, unexpected auth_type=%d:%s",
auth_key->auth_type,
bfd_auth_type_str (auth_key->auth_type));
return 0;
case BFD_AUTH_TYPE_keyed_md5:
/* fallthrough */
case BFD_AUTH_TYPE_meticulous_keyed_md5:
vlib_log_err
(bm->log_class,
"internal error, not implemented, unexpected auth_type=%d:%s",
auth_key->auth_type, bfd_auth_type_str (auth_key->auth_type));
return 0;
case BFD_AUTH_TYPE_keyed_sha1:
/* fallthrough */
case BFD_AUTH_TYPE_meticulous_keyed_sha1:
#if WITH_LIBSSL > 0
do
{
const u32 seq_num = clib_net_to_host_u32 (((bfd_pkt_with_sha1_auth_t
*) pkt)->
sha1_auth.seq_num);
return bfd_verify_pkt_auth_seq_num (vm, bs, seq_num,
bfd_auth_type_is_meticulous
(auth_key->auth_type))
&& bfd_verify_pkt_auth_key_sha1 (pkt, pkt_size, bs, bfd_key_id,
auth_key);
}
while (0);
#else
vlib_log_err
(bm->log_class,
"internal error, attempt to use SHA1 without SSL support");
return 0;
#endif
}
return 0;
}
/**
* @brief verify bfd packet - authentication
*
* @param pkt
*
* @return 1 if bfd packet is valid
*/
int
bfd_verify_pkt_auth (vlib_main_t * vm, const bfd_pkt_t * pkt, u16 pkt_size,
bfd_session_t * bs)
{
if (bfd_pkt_get_auth_present (pkt))
{
/* authentication present in packet */
if (!bs->auth.curr_key)
{
/* currently not using authentication - can we turn it on? */
if (bs->auth.is_delayed && bs->auth.next_key)
{
/* yes, switch is scheduled - make sure the auth is valid */
if (bfd_verify_pkt_auth_key (vm, pkt, pkt_size, bs,
bs->auth.next_bfd_key_id,
bs->auth.next_key))
{
/* auth matches next key, do the switch, packet is valid */
bfd_session_switch_auth_to_next (bs);
return 1;
}
}
}
else
{
/* yes, using authentication, verify the key */
if (bfd_verify_pkt_auth_key (vm, pkt, pkt_size, bs,
bs->auth.curr_bfd_key_id,
bs->auth.curr_key))
{
/* verification passed, packet is valid */
return 1;
}
else
{
/* verification failed - but maybe we need to switch key */
if (bs->auth.is_delayed && bs->auth.next_key)
{
/* delayed switch present, verify if that key works */
if (bfd_verify_pkt_auth_key (vm, pkt, pkt_size, bs,
bs->auth.next_bfd_key_id,
bs->auth.next_key))
{
/* auth matches next key, switch key, packet is valid */
bfd_session_switch_auth_to_next (bs);
return 1;
}
}
}
}
}
else
{
/* authentication in packet not present */
if (pkt_size > sizeof (*pkt))
{
BFD_ERR ("BFD verification failed - unexpected packet size '%d' "
"(auth not present)", pkt_size);
return 0;
}
if (bs->auth.curr_key)
{
/* currently authenticating - could we turn it off? */
if (bs->auth.is_delayed && !bs->auth.next_key)
{
/* yes, delayed switch to NULL key is scheduled */
bfd_session_switch_auth_to_next (bs);
return 1;
}
}
else
{
/* no auth in packet, no auth in use - packet is valid */
return 1;
}
}
return 0;
}
void
bfd_consume_pkt (vlib_main_t * vm, bfd_main_t * bm, const bfd_pkt_t * pkt,
u32 bs_idx)
{
bfd_lock_check (bm);
bfd_session_t *bs = bfd_find_session_by_idx (bm, bs_idx);
if (!bs || (pkt->your_disc && pkt->your_disc != bs->local_discr))
{
return;
}
BFD_DBG ("Scanning bfd packet, bs_idx=%d", bs->bs_idx);
bs->remote_discr = pkt->my_disc;
bs->remote_state = bfd_pkt_get_state (pkt);
bs->remote_demand = bfd_pkt_get_demand (pkt);
bs->remote_diag = bfd_pkt_get_diag_code (pkt);
u64 now = bfd_time_now_nsec (vm, NULL);
bs->last_rx_nsec = now;
if (bfd_pkt_get_auth_present (pkt))
{
bfd_auth_type_e auth_type =
((bfd_pkt_with_common_auth_t *) (pkt))->common_auth.type;
switch (auth_type)
{
case BFD_AUTH_TYPE_reserved:
/* fallthrough */
case BFD_AUTH_TYPE_simple_password:
/* fallthrough */
case BFD_AUTH_TYPE_keyed_md5:
/* fallthrough */
case BFD_AUTH_TYPE_meticulous_keyed_md5:
vlib_log_crit (bm->log_class,
"internal error, unexpected auth_type=%d:%s",
auth_type, bfd_auth_type_str (auth_type));
break;
case BFD_AUTH_TYPE_keyed_sha1:
/* fallthrough */
case BFD_AUTH_TYPE_meticulous_keyed_sha1:
do
{
bfd_pkt_with_sha1_auth_t *with_sha1 =
(bfd_pkt_with_sha1_auth_t *) pkt;
bs->auth.remote_seq_number =
clib_net_to_host_u32 (with_sha1->sha1_auth.seq_num);
bs->auth.remote_seq_number_known = 1;
BFD_DBG ("Received sequence number %u",
bs->auth.remote_seq_number);
}
while (0);
}
}
bs->remote_desired_min_tx_nsec =
bfd_usec_to_nsec (clib_net_to_host_u32 (pkt->des_min_tx));
bs->remote_detect_mult = pkt->head.detect_mult;
bfd_set_remote_required_min_rx (bm, bs, now,
clib_net_to_host_u32 (pkt->req_min_rx));
bfd_set_remote_required_min_echo_rx (bm, bs, now,
clib_net_to_host_u32
(pkt->req_min_echo_rx));
if (bfd_pkt_get_final (pkt))
{
if (BFD_POLL_IN_PROGRESS == bs->poll_state)
{
BFD_DBG ("Poll sequence terminated, bs_idx=%u", bs->bs_idx);
bfd_set_poll_state (bs, BFD_POLL_NOT_NEEDED);
if (BFD_STATE_up == bs->local_state)
{
bfd_set_effective_required_min_rx (bm, bs,
clib_max (bs->echo *
bm->min_required_min_rx_while_echo_nsec,
bs->config_required_min_rx_nsec));
}
}
else if (BFD_POLL_IN_PROGRESS_AND_QUEUED == bs->poll_state)
{
/*
* next poll sequence must be delayed by at least the round trip
* time, so calculate that here
*/
BFD_DBG ("Next poll sequence can commence in " BFD_CLK_FMT,
BFD_CLK_PRN (now - bs->poll_state_start_or_timeout_nsec));
bs->poll_state_start_or_timeout_nsec =
now + (now - bs->poll_state_start_or_timeout_nsec);
BFD_DBG
("Poll sequence terminated, but another is needed, bs_idx=%u",
bs->bs_idx);
bfd_set_poll_state (bs, BFD_POLL_NEEDED);
}
}
bfd_calc_next_tx (bm, bs, now);
bfd_set_timer (bm, bs, now, 0);
if (BFD_STATE_admin_down == bs->local_state)
{
BFD_DBG ("Session is admin-down, ignoring packet, bs_idx=%u",
bs->bs_idx);
return;
}
if (BFD_STATE_admin_down == bs->remote_state)
{
bfd_set_diag (bs, BFD_DIAG_CODE_neighbor_sig_down);
bfd_set_state (vm, bm, bs, BFD_STATE_down, 0);
}
else if (BFD_STATE_down == bs->local_state)
{
if (BFD_STATE_down == bs->remote_state)
{
bfd_set_diag (bs, BFD_DIAG_CODE_no_diag);
bfd_set_state (vm, bm, bs, BFD_STATE_init, 0);
}
else if (BFD_STATE_init == bs->remote_state)
{
bfd_set_diag (bs, BFD_DIAG_CODE_no_diag);
bfd_set_state (vm, bm, bs, BFD_STATE_up, 0);
}
}
else if (BFD_STATE_init == bs->local_state)
{
if (BFD_STATE_up == bs->remote_state ||
BFD_STATE_init == bs->remote_state)
{
bfd_set_diag (bs, BFD_DIAG_CODE_no_diag);
bfd_set_state (vm, bm, bs, BFD_STATE_up, 0);
}
}
else /* BFD_STATE_up == bs->local_state */
{
if (BFD_STATE_down == bs->remote_state)
{
bfd_set_diag (bs, BFD_DIAG_CODE_neighbor_sig_down);
bfd_set_state (vm, bm, bs, BFD_STATE_down, 0);
}
}
}
int
bfd_consume_echo_pkt (vlib_main_t * vm, bfd_main_t * bm, vlib_buffer_t * b)
{
bfd_echo_pkt_t *pkt = NULL;
if (b->current_length != sizeof (*pkt))
{
return 0;
}
pkt = vlib_buffer_get_current (b);
bfd_session_t *bs = bfd_find_session_by_disc (bm, pkt->discriminator);
if (!bs)
{
return 0;
}
BFD_DBG ("Scanning bfd echo packet, bs_idx=%d", bs->bs_idx);
u64 checksum =
bfd_calc_echo_checksum (bs->local_discr, pkt->expire_time_nsec,
bs->echo_secret);
if (checksum != pkt->checksum)
{
BFD_DBG ("Invalid echo packet, checksum mismatch");
return 1;
}
u64 now = bfd_time_now_nsec (vm, NULL);
if (pkt->expire_time_nsec < now)
{
BFD_DBG ("Stale packet received, expire time %lu < now %lu",
pkt->expire_time_nsec, now);
}
else
{
bs->echo_last_rx_nsec = now;
}
return 1;
}
u8 *
format_bfd_session (u8 * s, va_list * args)
{
const bfd_session_t *bs = va_arg (*args, bfd_session_t *);
s = format (s, "bs_idx=%u local-state=%s remote-state=%s\n"
"local-discriminator=%u remote-discriminator=%u\n"
"local-diag=%s echo-active=%s\n"
"desired-min-tx=%u required-min-rx=%u\n"
"required-min-echo-rx=%u detect-mult=%u\n"
"remote-min-rx=%u remote-min-echo-rx=%u\n"
"remote-demand=%s poll-state=%s\n"
"auth: local-seq-num=%u remote-seq-num=%u\n"
" is-delayed=%s\n"
" curr-key=%U\n"
" next-key=%U",
bs->bs_idx, bfd_state_string (bs->local_state),
bfd_state_string (bs->remote_state), bs->local_discr,
bs->remote_discr, bfd_diag_code_string (bs->local_diag),
(bs->echo ? "yes" : "no"), bs->config_desired_min_tx_usec,
bs->config_required_min_rx_usec, 1, bs->local_detect_mult,
bs->remote_min_rx_usec, bs->remote_min_echo_rx_usec,
(bs->remote_demand ? "yes" : "no"),
bfd_poll_state_string (bs->poll_state),
bs->auth.local_seq_number, bs->auth.remote_seq_number,
(bs->auth.is_delayed ? "yes" : "no"),
format_bfd_auth_key, bs->auth.curr_key, format_bfd_auth_key,
bs->auth.next_key);
return s;
}
u8 *
format_bfd_session_brief (u8 * s, va_list * args)
{
const bfd_session_t *bs = va_arg (*args, bfd_session_t *);
s =
format (s, "bs_idx=%u local-state=%s remote-state=%s", bs->bs_idx,
bfd_state_string (bs->local_state),
bfd_state_string (bs->remote_state));
return s;
}
unsigned
bfd_auth_type_supported (bfd_auth_type_e auth_type)
{
if (auth_type == BFD_AUTH_TYPE_keyed_sha1 ||
auth_type == BFD_AUTH_TYPE_meticulous_keyed_sha1)
{
return 1;
}
return 0;
}
vnet_api_error_t
bfd_auth_activate (bfd_session_t * bs, u32 conf_key_id,
u8 bfd_key_id, u8 is_delayed)
{
bfd_main_t *bm = &bfd_main;
const uword *key_idx_p =
hash_get (bm->auth_key_by_conf_key_id, conf_key_id);
if (!key_idx_p)
{
vlib_log_err (bm->log_class,
"authentication key with config ID %u doesn't exist)",
conf_key_id);
return VNET_API_ERROR_BFD_ENOENT;
}
const uword key_idx = *key_idx_p;
bfd_auth_key_t *key = pool_elt_at_index (bm->auth_keys, key_idx);
if (is_delayed)
{
if (bs->auth.next_key == key)
{
/* already using this key, no changes required */
return 0;
}
bs->auth.next_key = key;
bs->auth.next_bfd_key_id = bfd_key_id;
bs->auth.is_delayed = 1;
}
else
{
if (bs->auth.curr_key == key)
{
/* already using this key, no changes required */
return 0;
}
if (bs->auth.curr_key)
{
--bs->auth.curr_key->use_count;
}
bs->auth.curr_key = key;
bs->auth.curr_bfd_key_id = bfd_key_id;
bs->auth.is_delayed = 0;
}
++key->use_count;
BFD_DBG ("\nSession auth modified: %U", format_bfd_session, bs);
vlib_log_info (bm->log_class, "session auth modified: %U",
format_bfd_session_brief, bs);
return 0;
}
vnet_api_error_t
bfd_auth_deactivate (bfd_session_t * bs, u8 is_delayed)
{
bfd_main_t *bm = &bfd_main;
#if WITH_LIBSSL > 0
if (!is_delayed)
{
/* not delayed - deactivate the current key right now */
if (bs->auth.curr_key)
{
--bs->auth.curr_key->use_count;
bs->auth.curr_key = NULL;
}
bs->auth.is_delayed = 0;
}
else
{
/* delayed - mark as so */
bs->auth.is_delayed = 1;
}
/*
* clear the next key unconditionally - either the auth change is not delayed
* in which case the caller expects the session to not use authentication
* from this point forward, or it is delayed, in which case the next_key
* needs to be set to NULL to make it so in the future
*/
if (bs->auth.next_key)
{
--bs->auth.next_key->use_count;
bs->auth.next_key = NULL;
}
BFD_DBG ("\nSession auth modified: %U", format_bfd_session, bs);
vlib_log_info (bm->log_class, "session auth modified: %U",
format_bfd_session_brief, bs);
return 0;
#else
vlib_log_err (bm->log_class,
"SSL missing, cannot deactivate BFD authentication");
return VNET_API_ERROR_BFD_NOTSUPP;
#endif
}
vnet_api_error_t
bfd_session_set_params (bfd_main_t * bm, bfd_session_t * bs,
u32 desired_min_tx_usec,
u32 required_min_rx_usec, u8 detect_mult)
{
if (bs->local_detect_mult != detect_mult ||
bs->config_desired_min_tx_usec != desired_min_tx_usec ||
bs->config_required_min_rx_usec != required_min_rx_usec)
{
BFD_DBG ("\nChanging session params: %U", format_bfd_session, bs);
switch (bs->poll_state)
{
case BFD_POLL_NOT_NEEDED:
if (BFD_STATE_up == bs->local_state ||
BFD_STATE_init == bs->local_state)
{
/* poll sequence is not needed for detect multiplier change */
if (bs->config_desired_min_tx_usec != desired_min_tx_usec ||
bs->config_required_min_rx_usec != required_min_rx_usec)
{
bfd_set_poll_state (bs, BFD_POLL_NEEDED);
}
}
break;
case BFD_POLL_NEEDED:
case BFD_POLL_IN_PROGRESS_AND_QUEUED:
/*
* nothing to do - will be handled in the future poll which is
* already scheduled for execution
*/
break;
case BFD_POLL_IN_PROGRESS:
/* poll sequence is not needed for detect multiplier change */
if (bs->config_desired_min_tx_usec != desired_min_tx_usec ||
bs->config_required_min_rx_usec != required_min_rx_usec)
{
BFD_DBG ("Poll in progress, queueing extra poll, bs_idx=%u",
bs->bs_idx);
bfd_set_poll_state (bs, BFD_POLL_IN_PROGRESS_AND_QUEUED);
}
}
bs->local_detect_mult = detect_mult;
bs->config_desired_min_tx_usec = desired_min_tx_usec;
bs->config_desired_min_tx_nsec = bfd_usec_to_nsec (desired_min_tx_usec);
bs->config_required_min_rx_usec = required_min_rx_usec;
bs->config_required_min_rx_nsec =
bfd_usec_to_nsec (required_min_rx_usec);
BFD_DBG ("\nChanged session params: %U", format_bfd_session, bs);
vlib_log_info (bm->log_class, "changed session params: %U",
format_bfd_session_brief, bs);
vlib_process_signal_event (bm->vlib_main, bm->bfd_process_node_index,
BFD_EVENT_CONFIG_CHANGED, bs->bs_idx);
}
else
{
BFD_DBG ("Ignore parameter change - no change, bs_idx=%u", bs->bs_idx);
}
return 0;
}
vnet_api_error_t
bfd_auth_set_key (u32 conf_key_id, u8 auth_type, u8 key_len,
const u8 * key_data)
{
bfd_main_t *bm = &bfd_main;
#if WITH_LIBSSL > 0
bfd_auth_key_t *auth_key = NULL;
if (!key_len || key_len > bfd_max_key_len_for_auth_type (auth_type))
{
vlib_log_err (bm->log_class,
"invalid authentication key length for auth_type=%d:%s "
"(key_len=%u, must be non-zero, expected max=%u)",
auth_type, bfd_auth_type_str (auth_type), key_len,
(u32) bfd_max_key_len_for_auth_type (auth_type));
return VNET_API_ERROR_INVALID_VALUE;
}
if (!bfd_auth_type_supported (auth_type))
{
vlib_log_err (bm->log_class, "unsupported auth type=%d:%s", auth_type,
bfd_auth_type_str (auth_type));
return VNET_API_ERROR_BFD_NOTSUPP;
}
uword *key_idx_p = hash_get (bm->auth_key_by_conf_key_id, conf_key_id);
if (key_idx_p)
{
/* modifying existing key - must not be used */
const uword key_idx = *key_idx_p;
auth_key = pool_elt_at_index (bm->auth_keys, key_idx);
if (auth_key->use_count > 0)
{
vlib_log_err (bm->log_class,
"authentication key with conf ID %u in use by %u BFD "
"session(s) - cannot modify", conf_key_id,
auth_key->use_count);
return VNET_API_ERROR_BFD_EINUSE;
}
}
else
{
/* adding new key */
pool_get (bm->auth_keys, auth_key);
auth_key->conf_key_id = conf_key_id;
hash_set (bm->auth_key_by_conf_key_id, conf_key_id,
auth_key - bm->auth_keys);
}
auth_key->auth_type = auth_type;
clib_memset (auth_key->key, 0, sizeof (auth_key->key));
clib_memcpy (auth_key->key, key_data, key_len);
return 0;
#else
vlib_log_err (bm->log_class,
"SSL missing, cannot manipulate authentication keys");
return VNET_API_ERROR_BFD_NOTSUPP;
#endif
}
vnet_api_error_t
bfd_auth_del_key (u32 conf_key_id)
{
#if WITH_LIBSSL > 0
bfd_auth_key_t *auth_key = NULL;
bfd_main_t *bm = &bfd_main;
uword *key_idx_p = hash_get (bm->auth_key_by_conf_key_id, conf_key_id);
if (key_idx_p)
{
/* deleting existing key - must not be used */
const uword key_idx = *key_idx_p;
auth_key = pool_elt_at_index (bm->auth_keys, key_idx);
if (auth_key->use_count > 0)
{
vlib_log_err (bm->log_class,
"authentication key with conf ID %u in use by %u BFD "
"session(s) - cannot delete", conf_key_id,
auth_key->use_count);
return VNET_API_ERROR_BFD_EINUSE;
}
hash_unset (bm->auth_key_by_conf_key_id, conf_key_id);
clib_memset (auth_key, 0, sizeof (*auth_key));
pool_put (bm->auth_keys, auth_key);
}
else
{
/* no such key */
vlib_log_err (bm->log_class,
"authentication key with conf ID %u does not exist",
conf_key_id);
return VNET_API_ERROR_BFD_ENOENT;
}
return 0;
#else
vlib_log_err (bm->log_class,
"SSL missing, cannot manipulate authentication keys");
return VNET_API_ERROR_BFD_NOTSUPP;
#endif
}
bfd_main_t bfd_main;
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
|