[169543] in North American Network Operators' Group

home help back first fref pref prev next nref lref last post

Re: Managing IOS Configuration Snippets

daemon@ATHENA.MIT.EDU (Elle Janet Plato)
Sun Mar 2 16:43:39 2014

From: Elle Janet Plato <plato@wisc.edu>
Date: Sun, 02 Mar 2014 14:56:10 -0600
To: rdrake@direcpath.com
Cc: nanog@nanog.org, Elle Janet Plato <plato@wisc.edu>
Errors-To: nanog-bounces+nanog.discuss=bloom-picayune.mit.edu@nanog.org


--Apple-Mail=_A80B7261-9532-4BB6-AFE4-412ADCAA3257
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=us-ascii

Robert,

>> sgrep can dump out a "stanza" of ios-like config, then you can =
rcsdiff
>> that to your master, per 'chunk' of config.
>> Dale
>>
>
> I'm digging the idea of your command.   Along the same lines I've got =
this
> awk snippet that I made and then forgot about.  It functions like the =
cisco
> pipe begin/end commands:
>

The clever part comes when you write something to tweak sgrep to spit =
out files with the commands you need to run to reconfigure multiple =
devices, and then use the "make" command to invoke clogin in parallel to =
push those changes.  Showing a complete example would get tedious, I =
have a tarball of the minimum fileset needed to do this lying around =
somewhere.  Dale probably has one as well.

The basic workflow is as follows:

1) Given a set of configuration files named device.conf, generate a set =
of configuration changes to be made, and place those changes in a set of =
files named device.cmd.  Device is the valid hostname of a router/switch =
you need to configure.  Device.conf is the configuration file for that =
device, for example from rancid.  The contents of device.cmd are valid =
config commands including "config term", "exit" and "write mem", that =
you intend to run on the device.  We will talk about what to do with =
those command files in a later step.

So if you wanted to edit the name of vlan100 on all of your routers, you =
might do this:
  for device in `ls r-*.conf | cut -d. -f1`;
      do sgrep -is "^vlan 10\n" $device.conf | sed -e 's/name .*/name =
new-name/' | grep -v Found > $device.cmd;
      done

r-myrouter-100.cmd might contain:
vlan 10
 name new-name
!

So you would need to make your loop more complex to add the "conf t", =
"exit" and "wr mem" parts, or just use a script.  I write a script =
called mkcmdfile to wrap sgrep every time I need to do work like this.  =
mkcmdfile means "make command file".  If you want to work from the =
command line, add a second sed rule to look for "Found" and replace it =
with "conf t", eliminate the trailing grep -v "Found" and edit the =
original sed to replace vlan new-name with vlan new-name\nexit\nwr mem/. =
 I don't recommend doing that, but you could.  I put that into a wrapper =
script, or I post process the cmd files with a second for loop.

Now that is the less hard way to change 4,000 devices.  Except for made =
up examples like renaming a vlan on 4,000 devices, that is only a little =
less complicated than just doing it by hand, but hopefully you get the =
idea.

One huge win though, even when doing it by hand as above, I can generate =
the files ahead of time, ensure they are correct, and then when I push =
them at 4AM I do not have to worry about typographic errors.  If you =
have change approval boards, the CAB can examine the .cmd files if they =
choose to, this is a great way to sanity check your work at 2PM when =
your mind is clear.

  Loops are cool, but in reality, I am far more likely to edit sgrep =
with some reasonable defaults, hand it a list of filenames, and then =
rely on $ARGV changing to reflect the name of the file it is currently =
working on, so I know that when I have a diamond loop (for (<>) { do =
stuff }) in my Perl, $ARGV.conf is what sgrep is reading from, and =
$ARGV.cmd is the file sgrep should be writing to.  In fact, I have =
something I call mkcmdfile that does pretty much that.

Writing a custom sgrep for each change allows me to consider the entire =
contents of the router, including its name, the business rules =
associated with it, anything I keep in a database, etc, when making =
configuration changes to it.

Don't worry too much about how to do step 1.  The lesson you must =
understand, is that step 1 is finished when you have a directory full of =
files, all named device.cmd, where device is the name of the device to =
work on, and the contents are the commands to execute.

2) Given a directory full of command files (named device.cmd) invoke =
clogin on each file:
   The hard way would be another for loop:
   for device in `ls *.cmd | cut -d. -f1`;=20
       do clogin -s $device.cmd $device > $device.log;
       done

   I go into how to do this easily using make later.

3) Look at the resulting $device.log files you generated, and make sure =
nothing crazy happened. =20




  It really is that simple.  I can create cmd files for 4,000 devices, =
ensure the cmd files are changing the correct interface properties, ntp =
server names or whatever, and push them to all 4,000 devices, in a few =
hours.  Doing that by hand would take a week.  In some cases, I can push =
them in 30 minutes.

I have the minimum fileset you need to do that lying around somewhere, =
but basically that is it.


When I wrote sgrep, I was asking myself, what would happen if I make a =
tool that had more computing power than a tool that works on regular =
expressions?  grep gets its name from: global - 'regular expression' - =
print.  But regular expressions are limited in the computing complexity =
they can reflect.  I really wanted something turing complete.  But I =
never found a way to do it, that was less complex than inventing a new =
language.  Eventually I decided to have it think in terms of stanzas, =
and the operations you could perform on a stanza.  I started thinking =
about structure.  When you understand structure, you can look at things =
with more finesse.  Thanks to Dale, sgrep understands networks, so this =
means you can look for OSPF stanzas with network statements that contain =
a network range that would include a specific IP address.  If you grep =
for 10.1.2.3 in a router, you won't find the OSPF stanza with network =
10.1.2.0 255.255.255.0, but sgrep will.

I am thinking about a template language for sgrep, and once I write it I =
will let Dale know and he can put it on his page.  The thing is, start =
with grep, and ask what has more power than a regular expression?  =
Adding context is a logical next step, REs are context free.  Then ask, =
does using this structure with more capability result in clarity in how =
I express my will, and is it easy to understand, especially for people =
familiar with normal unix tools.

Anyway, to expand on automating this with make a little.  Dave Plonka =
made some cool makefiles, and we've been tweaking them every since.

Step 1 is always figuring out how to generate command files.  I have a =
mkcmdfile script I use and customize often for anything more complicated =
than a password change, or vlan edit.

Step 2 is always pushing those device.cmd files to the various devices =
they refer to.

Step 3 is always validating your work.


Let us expand on step 2.

When done with step 1, you have a bunch of device.cmd files, but you are =
no closer to getting work done than when you started.  But you need to =
understand the first step before the second step makes sense.  So given =
a directory full of .cmd files, you want to run those commands on the =
associated devices.

   - The hard way would be to invoke clogin directly (ensuring the file =
has conf t and write mem in it).
     for $device in `ls *.cmd | cut -d. -f1`; do clogin -s $device.cmd; =
done

   - The slightly less hard way would be to create a makefile with the =
following in it, and by hand add a rule to make all the .log files:

cat > Makefile
clogin =3D path-to/clogin2 -f path-to/.cloginrc
.SUFFIXES: .cmd .log

DIR =3D /home/netconfig-user/cms

TMPupgrade: device1.log, device2.log, device3.log, repeat for several =
thousand devices, hire an intern, a typist, whatever.

.cmd.log:
        @echo BEGIN .cmd.log $@
        base=3D'$*'; \
        $(clogin) $${clogin_timeout:+-t$${clogin_timeout}} -x $< =
$${base%%_*} > $@ || (rm -f $@; exit 1)
        @echo END .cmd.log $@
ctrl-D

Sure, that looks easy to read.  Did my modem disconnect?  It just says, =
if you run "make device.log" it will look for a command file named =
device.cmd, and compile it using the 'clogin' compiler, with the =
options:

    clogin -t timeout -x device.cmd device > device.log, the or (||) =
means, if the command fails, instead of crashing just rm the .log file =
and continue with the next file.=20


Given that, you could invoke make and it would be off and running, but =
that gets awfully tedious for one thousand devices.

    $configbox>  make -j 20 TMPupgrade.

Boom, 20 at a time your system is clogin-ing into devices and pushing =
commmands.

So the better way is you add an extra rule to make the makefile you =
want, and then use that to invoke clogin:

cat > Makefile
clogin =3D path-to/clogin2 -f path-to/.cloginrc
.SUFFIXES: .cmd .log

DIR =3D /home/netconfig-user/cms

upgrade.make:
        @print "TMPupgrade: " $$($(ls) *.cmd | sed -e =
's/\.cmd$$/.log/')" \
        \n\nupgrade: " $$($(ls) *.cmd | sed -e 's/\.cmd$$/.log/')" \
        \n\ninclude ~net/cms/Makefile" > $@

.cmd.log:
        @echo BEGIN .cmd.log $@
        base=3D'$*'; \
        $(clogin) $${clogin_timeout:+-t$${clogin_timeout}} -x $< =
$${base%%_*} > $@ || (rm -f $@; exit 1)
        @echo END .cmd.log $@
ctrl-D

Given the above makefile, you can make a new makefile with the correct =
targets.

    $configbox> make upgrade

This will use sed to replace the .cmd with a .log for every device.cmd =
file, and create a new makefile with a rule to make all the .log files.  =
Again, I should have the correct minimum fileset lying around somewhere, =
if someone wants help I can try and make a better explanation and post =
it.

Once you have the new makefile, just use it.

$configbox> make -f upgrade.make -j 20

The process really is pretty damn simple, but the details are kind of =
tedious.

Once you get used to it, you can whip out scripts to do complex =
validation rules in no time flat.  On Dale's page you will also find =
some code I got from Cisco to merge catos/IOS configs from a 6500 in =
hybrid mode to a unified IOS only mode, and merge them with a template.  =
I fixed some small bugs in it, and got permission to open source it.  =
That code parses IOS configs fairly elegantly and shoves them into Perl =
data structures, which you can then use to make savvy choices with =
respect to configuration auditing.  The code is open source, have at it. =
 You can validate the configs on your devices, and best of all, you can =
validate your business logic.  If you name all your primary routers =
something odd, and your backups something even, you can validate the =
ospf metrics on primary are different than the ospf metrics on the =
secondary, because the script understands not only the configuration, =
but how the device fits into the network, and what business logic =
applies to the configuration.

I hope this makes things clearer, instead of less clear.

Cheers,

Elle Janet Plato
NS Application Developer/Consultant Network Engineer
University of Wisconsin, Madison=

--Apple-Mail=_A80B7261-9532-4BB6-AFE4-412ADCAA3257
Content-Disposition: attachment;
	filename=smime.p7s
Content-Type: application/pkcs7-signature;
	name=smime.p7s
Content-Transfer-Encoding: base64

MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIZSTCCBJ8w
ggQIoAMCAQICBEaekRowDQYJKoZIhvcNAQEFBQAwgcMxCzAJBgNVBAYTAlVTMRQwEgYDVQQKEwtF
bnRydXN0Lm5ldDE7MDkGA1UECxMyd3d3LmVudHJ1c3QubmV0L0NQUyBpbmNvcnAuIGJ5IHJlZi4g
KGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxOjA4
BgNVBAMTMUVudHJ1c3QubmV0IFNlY3VyZSBTZXJ2ZXIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw
HhcNMDkwMzIzMTUxODI3WhcNMTkwMzIzMTU0ODI3WjCBtDEUMBIGA1UEChMLRW50cnVzdC5uZXQx
QDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxpbWl0
cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMT
KkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAK1NS6kShrLqoyAHFRZkKitL0b8LSk2O7YB2pWe3eEDAc0LIaMDb
UyvdXrh2mDWTixqdfBM6Dh9btx7P5SQUHrGBqY19uMxrSwPxAgzcq6VAJAB/dJShnQgps4gL9Yd3
nVXN5MN+12pkq4UUhpVblzJQbz3IumYM4/y9uEnBdolJGf3AqL2Jo2cvxp+8cRlguC3pLMmQdmZ7
lOKveNZlU1081pyyzykD+S+kULLUSM4FMlWK/bJkTA7kmAd123/fuQhVYIUwKfl7SKRphuM1Px6G
XXp6Fb3vAI4VIlQXAJAmk7wOSWiRv/hH052VQsEOTd9vJs/DGCFiZkNw1tXAB+ECAwEAAaOCAScw
ggEjMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MDMGCCsGAQUFBwEBBCcwJTAjBggr
BgEFBQcwAYYXaHR0cDovL29jc3AuZW50cnVzdC5uZXQwMwYDVR0fBCwwKjAooCagJIYiaHR0cDov
L2NybC5lbnRydXN0Lm5ldC9zZXJ2ZXIxLmNybDA7BgNVHSAENDAyMDAGBFUdIAAwKDAmBggrBgEF
BQcCARYaaHR0cDovL3d3dy5lbnRydXN0Lm5ldC9DUFMwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5
oSQJFrlwMB8GA1UdIwQYMBaAFPAXYhNVPbP/CgBr+1CEl/PtYtAaMBkGCSqGSIb2fQdBAAQMMAob
BFY3LjEDAgCBMA0GCSqGSIb3DQEBBQUAA4GBAI9lojCOJquK7DUWmOkD8I0XX7xMbAL2dFLgwsYf
zvKmEQyosQ5NhItxNu+zNUXzwfiWxYtVpMxrgxYgMtq++6+bt5/hfoSfnjxQpz9cwr6LhrgIku74
QisNE+N2hUgKSr/QpTsKsFS4beMI+TSNC46LEswXGjOHlcieCtxQUxd7MIIFozCCBIugAwIBAgIE
TA5iEjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3
dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAj
BgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0
IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw0xMDA2MzAxODM0NTRaFw0yMDA2MzAx
OTA0NTRaMIGAMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRW50cnVzdDEiMCAGA1UECxMZQ2VydGlm
aWNhdGlvbiBBdXRob3JpdGllczE7MDkGA1UEAxMyRW50cnVzdCBNYW5hZ2VkIFNlcnZpY2VzIENv
bW1lcmNpYWwgUHVibGljIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDM
XI+wxZoiWKTiB15DT/VyF8eTSWED/vatNS6/Y+s9kbGo2oI8Qlk/lsWn7lv9UeJmIVeu+Pp6iNTy
Q09kOAyBBmAQ/yKq4PRHnsrPuxgkirXZ5t3AumSPVr62v2kHVce9S94LjCR2UIov0EMvs8/qq95K
IGxGLTgdoeDVXI/5RZeAsGTquePKvbHest1FmPQaly2pRPdnlRHEmJQ2NkaR45AeQvKKn8kzpYeC
oBLyCsD0HbHzlIfPaujKqEcQZIbJUyD0y++KNajSPATWImCt2eXdeHEUcnmcHGq9ha1EEI02oW8z
T2R0xhjdLoR5Ds+xg43iGyxLPdoliIxHVPhhAgMBAAGjggHtMIIB6TAOBgNVHQ8BAf8EBAMCAQYw
EgYDVR0TAQH/BAgwBgEB/wIBATAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9v
Y3NwLmVudHJ1c3QubmV0MIIBGAYDVR0gBIIBDzCCAQswVwYNYIZIAYb6a4FIAwoCBDBGMEQGCCsG
AQUFBwIBFjhodHRwOi8vY29tcHViLm1hbmFnZWQuZW50cnVzdC5jb20vQ1AvRU1TQ29tbWVyY2lh
bENQLnBkZjBXBg1ghkgBhvprgUgDCgIFMEYwRAYIKwYBBQUHAgEWOGh0dHA6Ly9jb21wdWIubWFu
YWdlZC5lbnRydXN0LmNvbS9DUC9FTVNDb21tZXJjaWFsQ1AucGRmMFcGDWCGSAGG+muBSAMKAgYw
RjBEBggrBgEFBQcCARY4aHR0cDovL2NvbXB1Yi5tYW5hZ2VkLmVudHJ1c3QuY29tL0NQL0VNU0Nv
bW1lcmNpYWxDUC5wZGYwMgYDVR0fBCswKTAnoCWgI4YhaHR0cDovL2NybC5lbnRydXN0Lm5ldC8y
MDQ4Y2EuY3JsMB0GA1UdDgQWBBTAMkkFZmaDhxlpua6DJQYZiwXXdDAfBgNVHSMEGDAWgBRV5IHR
EYC+2Im5CKMx+aEkCRa5cDANBgkqhkiG9w0BAQUFAAOCAQEAD7NwMLoCbvFzWEObVh724gCE6XY+
xB2NpOrYpu7dlh98kzn7upnY1BMhjvLHiWDMcxIIsar/XFNI7AePCF4PGpvfudBtB/U5umTxFVYg
LLexxsN2cUOP5yd0mJb6k3wU6NOi8mPZNtSfullUs7avzGHWx787no9d97XrIKKCMV8HwJjtZCt0
OKFXVCYWMNMcFqVvBX2pbqgSlSBtZhzTIfi3MYkEOY9Zgrtsh+2hP22OJuskImNEHqlYbM//OqlC
GQz+4sK6Ai/3HMfKFKJ/6Oyf8j48dO123nPRMQAy/oBHEITGQQUK0hdDZyglGOzTHGWH2Ae33vrz
s+8T9rG8GzCCBxEwggX5oAMCAQICBEwfo4cwDQYJKoZIhvcNAQEFBQAwgYAxCzAJBgNVBAYTAlVT
MRAwDgYDVQQKEwdFbnRydXN0MSIwIAYDVQQLExlDZXJ0aWZpY2F0aW9uIEF1dGhvcml0aWVzMTsw
OQYDVQQDEzJFbnRydXN0IE1hbmFnZWQgU2VydmljZXMgQ29tbWVyY2lhbCBQdWJsaWMgUm9vdCBD
QTAeFw0xMDA3MDcyMDE0NTRaFw0zMDA2MDcyMDQ0NTRaMHcxCzAJBgNVBAYTAlVTMRAwDgYDVQQK
EwdFbnRydXN0MSIwIAYDVQQLExlDZXJ0aWZpY2F0aW9uIEF1dGhvcml0aWVzMTIwMAYDVQQDEylF
bnRydXN0IEVkdWNhdGlvbiBTaGFyZWQgU2VydmljZSBQcm92aWRlcjCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAOtRQhPAzU32kb0lQD4Zbvrz4z1/uMOXoAURJ8//Dm3SQFuuG+lDwyE4
zkk85mtmqJgbGsA2cQOiv7189VBAHxgvOkc322Riwi5TKErPAk/tU9ay2Zne1S4oDeMiHp9Kpgde
0OcjKE7fx6PZmB/i0QWqVvm6C20cjFUcjYOs8QH79lh10w0bUuvR8/jk5FJ8Ss2cxDl2CIB826jC
ZW2SKsQ1LlRSJIJ9AOfn6fr/m5aBHCEoqAkrI0zK+CT3OTtMTRzoGvyh9Wv2oWVVOjlpUdD5Htxu
FrDmps4Z2ZAE3+KCpX0G183hhEKzBRIDv3eC1Wv8J2mG/s+aNRqcgLmWFQcCAwEAAaOCA5kwggOV
MA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMDwGA1UdIAQ1MDMwDwYNYIZIAYb6
a4FIAwoCBDAPBg1ghkgBhvprgUgDCgIFMA8GDWCGSAGG+muBSAMKAgYwggE/BggrBgEFBQcBAQSC
ATEwggEtMFUGCCsGAQUFBzAChklodHRwOi8vY29tcHVid2ViLm1hbmFnZWQuZW50cnVzdC5jb20v
QUlBL0NlcnRzSXNzdWVkVG9FTVNDb21QdWJSb290Q0EucDdjMIHTBggrBgEFBQcwAoaBxmxkYXA6
Ly9jb21wdWJzaGFkLm1hbmFnZWQuZW50cnVzdC5jb20vb3U9RW50cnVzdCUyME1hbmFnZWQlMjBT
ZXJ2aWNlcyUyMENvbW1lcmNpYWwlMjBQdWJsaWMlMjBSb290JTIwQ0Esb3U9Q2VydGlmaWNhdGlv
biUyMEF1dGhvcml0aWVzLG89RW50cnVzdCxjPVVTP2NBQ2VydGlmaWNhdGU7YmluYXJ5LGNyb3Nz
Q2VydGlmaWNhdGVQYWlyO2JpbmFyeTCCAawGA1UdHwSCAaMwggGfMIH+oIH7oIH4hj1odHRwOi8v
Y29tcHVid2ViLm1hbmFnZWQuZW50cnVzdC5jb20vQ1JMcy9FTVNDb21QdWJSb290Q0EuY3JshoG2
bGRhcDovL2NvbXB1YnNoYWQubWFuYWdlZC5lbnRydXN0LmNvbS9jbj1FbnRydXN0JTIwTWFuYWdl
ZCUyMFNlcnZpY2VzJTIwQ29tbWVyY2lhbCUyMFB1YmxpYyUyMFJvb3QlMjBDQSxvdT1DZXJ0aWZp
Y2F0aW9uJTIwQXV0aG9yaXRpZXMsbz1FbnRydXN0LGM9VVM/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
TGlzdDtiaW5hcnkwgZuggZiggZWkgZIwgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFbnRydXN0
MSIwIAYDVQQLExlDZXJ0aWZpY2F0aW9uIEF1dGhvcml0aWVzMTswOQYDVQQDEzJFbnRydXN0IE1h
bmFnZWQgU2VydmljZXMgQ29tbWVyY2lhbCBQdWJsaWMgUm9vdCBDQTENMAsGA1UEAxMEQ1JMMTAf
BgNVHSMEGDAWgBTAMkkFZmaDhxlpua6DJQYZiwXXdDAdBgNVHQ4EFgQUIt2i+lhOgz5TiwGAExY1
1IEVtn8wDQYJKoZIhvcNAQEFBQADggEBAHQ4kWFG0YwlCojUFLo5/Btbxr51qNZL52Mf5QVC9O09
b7YZE1ZcAUJlYxerhKPV66xQAhro9ch/VUYDKu1/qTAX5OGRH5sq5lBO2RatB7tEyEuY3S6SWXCs
Jcvyi7eUrPov5Ojo0GsMymqNbdU+Uy/e3I58daQx9BzVGIGXg8iAxt+7cG4NtiXeCOXXfjPemC/O
xuzH9k6SEv16ztlnfOFBJVs5jI1iKCtKDSd74K/k3CgvBK8zEvgLjXzLgWS/pUqIv8jjhAFEu0pf
xsXkpn69ORT3pw972+q+A2rg8lilyd9KIzvcpi07orohVeXnQ+67NIscURgNDDtfFRWrq3cwggfm
MIIGzqADAgECAgRMIER3MA0GCSqGSIb3DQEBBQUAMHcxCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdF
bnRydXN0MSIwIAYDVQQLExlDZXJ0aWZpY2F0aW9uIEF1dGhvcml0aWVzMTIwMAYDVQQDEylFbnRy
dXN0IEVkdWNhdGlvbiBTaGFyZWQgU2VydmljZSBQcm92aWRlcjAeFw0xMzA2MjgxOTEwMDJaFw0x
ODA2MjgxOTQwMDJaMIGgMQswCQYDVQQGEwJVUzESMBAGA1UECBMJV2lzY29uc2luMSAwHgYDVQQK
ExdVbml2ZXJzaXR5IG9mIFdpc2NvbnNpbjEQMA4GA1UECxMHTWFkaXNvbjFJMBEGA1UEBRMKMDAw
MDAwMTc0MDAXBgNVBAMTEEVsbGUgSmFuZXQgUGxhdG8wGwYJKoZIhvcNAQkBFg5wbGF0b0B3aXNj
LmVkdTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK2ZunUK1zxm+VK/HjCF8BPSTxQO
40zDUnjJ/kmguBnseEB9FF3FKpnFPKZZGZo/Tx6hegwzUazNE9zt+B2pfSSUuvYuOhFWKjdqYmKv
3EWeJ0zggmCZDskZJzFv8Z294nzShzUZFoXaeQXqpbEEA+F4+UK3U3kNfApSZ1gAcv6oMMtFMARB
BKWhO06M7ajG7hnOLyGYZxHyyvLE1brrhRd1kVpep6W8NAq4KWZrSFWBN6Fv2UJ5bSaxfQj4gtcy
wc4rBjrULwX4wYgp6HYue1p/tuZEqrLcUHmeTTZ4KVOoKmvpNpboQNRzqknskpc5O9I7qwN64Kx7
hjwC0ivyF/kCAwEAAaOCBE4wggRKMA4GA1UdDwEB/wQEAwIFoDAmBgNVHSUEHzAdBggrBgEFBQcD
AgYIKwYBBQUHAwQGBysGAQUCAwQwggEzBggrBgEFBQcBAQSCASUwggEhMFMGCCsGAQUFBzAChkdo
dHRwOi8vZWR1Y2F0aW9ud2ViLm1hbmFnZWQuZW50cnVzdC5jb20vQUlBL0NlcnRzSXNzdWVkVG9F
TVNFZFNTUENBLnA3YzCByQYIKwYBBQUHMAKGgbxsZGFwOi8vZWR1Y2F0aW9uc2hhZC5tYW5hZ2Vk
LmVudHJ1c3QuY29tL2NuPUVudHJ1c3QlMjBFZHVjYXRpb24lMjBTaGFyZWQlMjBTZXJ2aWNlJTIw
UHJvdmlkZXIsb3U9Q2VydGlmaWNhdGlvbiUyMEF1dGhvcml0aWVzLG89RW50cnVzdCxjPVVTP2NB
Q2VydGlmaWNhdGU7YmluYXJ5LGNyb3NzQ2VydGlmaWNhdGVQYWlyO2JpbmFyeTArBgNVHSAEJDAi
MA8GDWCGSAGG+muBSAMKAgQwDwYNYIZIAYb6a4FIAwoCBTBYBglghkgBhvprHgEESwxJVGhlIHBy
aXZhdGUga2V5IGNvcnJlc3BvbmRpbmcgdG8gdGhpcyBjZXJ0aWZpY2F0ZSBtYXkgaGF2ZSBiZWVu
IGV4cG9ydGVkLjAZBgNVHREEEjAQgQ5wbGF0b0B3aXNjLmVkdTCCAaIGA1UdHwSCAZkwggGVMIH9
oIH6oIH3hkZodHRwOi8vZWR1Y2F0aW9ud2ViLm1hbmFnZWQuZW50cnVzdC5jb20vQ1JMcy9FbnRy
dXN0RURVQ0FUSU9OU1NQQ0EuY3JshoGsbGRhcDovL2VkdWNhdGlvbnNoYWQubWFuYWdlZC5lbnRy
dXN0LmNvbS9jbj1FbnRydXN0JTIwRWR1Y2F0aW9uJTIwU2hhcmVkJTIwU2VydmljZSUyMFByb3Zp
ZGVyLG91PUNlcnRpZmljYXRpb24lMjBBdXRob3JpdGllcyxvPUVudHJ1c3QsYz1VUz9jZXJ0aWZp
Y2F0ZVJldm9jYXRpb25MaXN0O2JpbmFyeTCBkqCBj6CBjKSBiTCBhjELMAkGA1UEBhMCVVMxEDAO
BgNVBAoTB0VudHJ1c3QxIjAgBgNVBAsTGUNlcnRpZmljYXRpb24gQXV0aG9yaXRpZXMxMjAwBgNV
BAMTKUVudHJ1c3QgRWR1Y2F0aW9uIFNoYXJlZCBTZXJ2aWNlIFByb3ZpZGVyMQ0wCwYDVQQDEwRD
Ukw0MCsGA1UdEAQkMCKADzIwMTMwNjI4MTkxMDAyWoEPMjAxNjEyMjcyMzQwMDJaMB8GA1UdIwQY
MBaAFCLdovpYToM+U4sBgBMWNdSBFbZ/MB0GA1UdDgQWBBR1pFykfG9uoIqEUYS8HsiScVjtRjAJ
BgNVHRMEAjAAMBkGCSqGSIb2fQdBAAQMMAobBFY4LjEDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQCt
Rof/RoN268asOh+mQs5aiBkrW9BJjCOBPX+oVAiVVmw1GDy+zlT8touqOhQPheMhlEt80y9Sbmve
f2fEITWd0RUgJZ/ckQsIOeTD7P2eASnSEvT5qVVxGqGeVboRqGqm3uDvPuynzxJsAyqlzT+UV+Sx
+PEn574PA74DG1cnlf0MR43AJIdIRbakNEj4GNVxZyHPjoLmttTcN+vnKLfVnlpiOElIeiQUWjey
bPb5APLbtHhH7miz2KGuY6nOrD0+mlu03G/O7pekzxE99pWuoyJTXMFXo+GdYwnWYYPmi35lDbnl
d6wxYbfndCBMQdf4+H2cuQn9HQDQVhlZduZqMYIDLTCCAykCAQEwfzB3MQswCQYDVQQGEwJVUzEQ
MA4GA1UEChMHRW50cnVzdDEiMCAGA1UECxMZQ2VydGlmaWNhdGlvbiBBdXRob3JpdGllczEyMDAG
A1UEAxMpRW50cnVzdCBFZHVjYXRpb24gU2hhcmVkIFNlcnZpY2UgUHJvdmlkZXICBEwgRHcwCQYF
Kw4DAhoFAKCCAYMwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTQw
MzAyMjA1NjExWjAjBgkqhkiG9w0BCQQxFgQU5GJR4rbeMOIG46aFJDRrJ8gamtswgY8GCSsGAQQB
gjcQBDGBgTB/MHcxCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFbnRydXN0MSIwIAYDVQQLExlDZXJ0
aWZpY2F0aW9uIEF1dGhvcml0aWVzMTIwMAYDVQQDEylFbnRydXN0IEVkdWNhdGlvbiBTaGFyZWQg
U2VydmljZSBQcm92aWRlcgIETCBEdzCBkQYLKoZIhvcNAQkQAgsxgYGgfzB3MQswCQYDVQQGEwJV
UzEQMA4GA1UEChMHRW50cnVzdDEiMCAGA1UECxMZQ2VydGlmaWNhdGlvbiBBdXRob3JpdGllczEy
MDAGA1UEAxMpRW50cnVzdCBFZHVjYXRpb24gU2hhcmVkIFNlcnZpY2UgUHJvdmlkZXICBEwgRHcw
DQYJKoZIhvcNAQEBBQAEggEAe+BncYlQIGtK/28x9bnFHdPJpHLbufzX1sJ+bEQf3TnQBe/WYGhV
L7JXwfmNxMtJSjLk6KR4crPoc/azF+nyBRCBUgUn7cFZXOAFOzSpP8n3y6VsZmT6XjKUb2GGEIxN
1bUDPp5YIsLHvuIbPK1ZalpCmN0UOa5XKTRPsmL4PNTtQqVYU/kUYhRoswIvJFY2BwAO0pwIvUHA
OC5uUuSBTMHlAfWbA2MTGYxbDxZgZJzqA+AjaecfwqmLdVNtukPoK38Z5S0KHjfeC+JNWLaBiVaU
Hv+2Z1Jmga81O0g0LXZlNran1Mxvb43B7fF5d1CIsUxauS9n4hkLCXEPh3CQoQAAAAAAAA==

--Apple-Mail=_A80B7261-9532-4BB6-AFE4-412ADCAA3257--


home help back first fref pref prev next nref lref last post