<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>108.bz &#187; IT</title>
	<atom:link href="http://www.108.bz/posts/category/it/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.108.bz</link>
	<description>Wandering futilities...</description>
	<lastBuildDate>Wed, 08 Sep 2010 13:45:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Oracle Reports Server font issues</title>
		<link>http://www.108.bz/posts/it/oracle-reports-server-font-issues/</link>
		<comments>http://www.108.bz/posts/it/oracle-reports-server-font-issues/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 13:45:53 +0000</pubDate>
		<dc:creator>Giuliano</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Troubleshooting]]></category>

		<guid isPermaLink="false">http://www.108.bz/?p=572</guid>
		<description><![CDATA[Here&#8217;s a couple of hints you may find useful when shooting troubles around Oracle Reports Server. It all starts when Customer wants to produce PDF reports using a custom font. Of course the font won&#8217;t be there when the file is opened on a client PC. The report server must either embed (include entirely) or [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a couple of hints you may find useful when shooting troubles around <a href="http://en.wikipedia.org/wiki/Oracle_reports">Oracle Reports Server</a>.<br />
It all starts when Customer wants to produce PDF reports using a custom font. Of course the font won&#8217;t be there when the file is opened on a client PC. The report server must either <i>embed</i> (include entirely) or <i>subset</i> (include just the actually used glyphs) the font into the PDF.</p>
<p>We&#8217;re running <a href="http://www.oracle.com/technology/documentation/appserver1012.html">Oracle Application Server 10g Release 2</a> on Windows.</p>
<p>More than one Reports Server (RS from now on) can be run at the same time. Each RS is identified by name. Open a DOS window, change directory to the one where reports templates/resources are, then launch:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">rwserver server=rstest</div></div>
<p><a href="http://www.108.bz/wp-content/uploads/2010/09/rsts01.png"><img src="http://www.108.bz/wp-content/uploads/2010/09/rsts01.png" alt="Test Oracle Reports Server is running" title="rsts01" width="390" height="200" class="aligncenter size-full wp-image-576" /></a></p>
<p>RS named &#8220;rstest&#8221; will get its own log directory and configuration file, under the Application Server &#8220;HOME&#8221;:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">reports\conf\rstest.conf<br />
reports\logs\rstest\<br />
reports\logs\rstest\rwserver.log</div></div>
<p>Quite convenient: you&#8217;ll leave the production RS alone, be able to activate debug tracing, restart at will, &#8230;</p>
<p>Here&#8217;s how tu run a test report on the &#8220;rstest&#8221; RS:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">rwclient SERVER=rstest REPORT=d01_skt_anag1.rdf userid=user/pwd@db DESFORMAT=pdf DESTYPE=file DESNAME=c:\temp\testoutput.pdf</div></div>
<p>Back to our issues. First step, I&#8217;d say, is to find out the exact name of the font we&#8217;d like to embed. Did you know you can convert Report Developer &#8220;source&#8221; files (<span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">.rdf</span>) to XML, then peek in them? Use:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">rwconverer STYPE=rdffile SOURCE=d01_skt_anag1.rdf DTYPE=xmlfile dest=c:\temp\rpt.xml</div></div>
<p>&#8220;Cooper Black&#8221; is the name:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">C:\dev\appl\Reports&gt;findstr /I face c:\temp\rpt.xml | findstr /I coop<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;font face=&quot;Cooper Black&quot; size=&quot;14&quot; bold=&quot;yes&quot; textColor=&quot;red&quot;/&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;font face=&quot;Cooper Black&quot; size=&quot;11&quot; bold=&quot;yes&quot; textColor=&quot;red&quot;/&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;font face=&quot;Cooper Black&quot; size=&quot;12&quot; bold=&quot;yes&quot; textColor=&quot;red&quot;/&gt;</div></div>
<p>Install the font in Windows. Oddly, things didn&#8217;t seem to work for me when I just copied the <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">.ttf</span> file in the <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">C:\WINDOWS\Fonts</span> directory. I had to use the &#8220;Install New Font&#8221; menu item. I thought both methods were equivalent, maybe I was wrong, maybe I&#8217;m talking junk now.</p>
<p><a href="http://www.108.bz/wp-content/uploads/2010/09/rsts03.png"><img src="http://www.108.bz/wp-content/uploads/2010/09/rsts03.png" alt="TTF font install in Windows" title="rsts03" width="377" height="257" class="aligncenter size-full wp-image-578" /></a></p>
<p>Modify the <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">uifont.ali</span> file (<span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">tools\common</span>), telling the Report Server to subset &#8220;Cooper Black&#8221; into the generated PDF files. Just add a line under the <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">PDF:Subset</span> section, equating the font name to the TTF file name, both enclosed in double quotes.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[ PDF:Subset ]<br />
&quot;Cooper Black&quot; = &quot;COOPBL.TTF&quot;</div></div>
<p>The <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">fnchk.exe</span> program (ran without arguments) displays the full path of <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">uifont.ali</span> and tells if everything is fine or the file contains any syntax error.</p>
<p>Installing the font in Windows is not enough, you should also put it in one of the <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">REPORTS_PATH</span> directories. The value of this variable can be found in the registry, I chose: <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">C:\Oracle\Products\FRHome\reports\templates</span>. <a href="http://en.wikipedia.org/wiki/Filemon">FileMon</a> is essential when trying to see which files can&#8217;t be found by a process.</p>
<p>Time to restart the Reports Service, generate a PDF report and check if fonts are good (in Acrobat Reader: CTRL-D, &#8220;Fonts&#8221; tab). Ours is listed as &#8220;Embedded Subset&#8221;; we&#8217;re done.</p>
<p><a href="http://www.108.bz/wp-content/uploads/2010/09/rsts06.png"><img src="http://www.108.bz/wp-content/uploads/2010/09/rsts06-294x300.png" alt="Embedded Subset Font in PDF" title="rsts06" width="294" height="300" class="aligncenter size-medium wp-image-580" /></a></p>
<p>See also: Oracle Support Note.350971.1 <i>&#8220;Troubleshooting Guide for Font Aliasing / Font Subsetting / Font Embedding Issues&#8221;</i>.</p>
 <img src="http://www.108.bz/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=572" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.108.bz/posts/it/oracle-reports-server-font-issues/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>From MS SQL to MySQL, realtime row copy</title>
		<link>http://www.108.bz/posts/it/from-ms-sql-to-mysql-realtime-row-copy/</link>
		<comments>http://www.108.bz/posts/it/from-ms-sql-to-mysql-realtime-row-copy/#comments</comments>
		<pubDate>Mon, 06 Sep 2010 13:26:42 +0000</pubDate>
		<dc:creator>Giuliano</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Interoperability]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.108.bz/?p=556</guid>
		<description><![CDATA[Or: &#8220;How to call a web server from a Microsoft SQL Server Stored Procedure&#8221;. Customer has got a VoIP software PBX (Swyx). It logs incoming calls (the CDR) in a MS SQL Server database. The CDR structure is straightforward: a single table where each row is a call, indexed by CallId (transferred calls get, eventually, [...]]]></description>
			<content:encoded><![CDATA[<p>Or: &#8220;How to call a web server from a Microsoft SQL Server Stored Procedure&#8221;.<br />
Customer has got a VoIP software PBX (<a href="http://www.swyx.com/">Swyx</a>). It logs incoming calls (the <abbr title="Call Detail Record">CDR</abbr>) in a MS SQL Server database. The CDR structure is straightforward: a single table where each row is a call, indexed by <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">CallId</span> (transferred calls get, eventually, a new row and a &#8220;child CallId&#8221;).<br />
I needed to process the CDR within these specs/restrictions:</p>
<ul>
<li>Each row has to be processed as soon as it is INSERTed</li>
<li>Rows must be filtered (depending on the called number)</li>
<li>Filtered rows must be &#8220;mirrored&#8221; to a MySQL DB</li>
<li>MS SQL machine is heavily loaded and mission critical; the row-copy mechanism must be light and fast</li>
</ul>
<p>The first and second specs imply the use of triggers/stored procedures.</p>
<p>I originally thought that the &#8220;DB link&#8221;-kind of functionality could be achieved natively on MS SQL. In theory it can, via <a href="http://msdn.microsoft.com/en-us/library/aa213778(SQL.80).aspx">Linked Servers</a> (<a href="http://www.ideaexcursion.com/2009/02/25/howto-setup-sql-server-linked-server-to-mysql/">bound</a> to ODBC Data Sources). There&#8217;s a catch though: you can SELECT stuff on linked servers at will, but as soon as you try to INSERT, you&#8217;ll hit error 7391<sup class='footnote'><a href='#fn-556-1' id='fnref-556-1'>1</a></sup>. MS SQL, can&#8217;t really blame it, would like to be able to rollback any change made, even on the linked MySQL. It needs to start a (implicit, distributed) transaction on MySQL, but that&#8217;s not supported and the write fails. <a href="http://forums.mysql.com/read.php?60,209856,256141#msg-256141">This</a> workaround (forcibly switch off implicit transactions) didn&#8217;t work for me. Apparently, the Oracle OLEDB Provider is able to ignore/disable distributing transactions when the parameter <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">DistribTX=0</span> is in the provider string. MySQL&#8217;s ODBC driver doesn&#8217;t provide a similar toggle.</p>
<p>The easiest way to push data &#8220;out&#8221; of MS SQL is (arguably) through HTTP. The DB GETs a full URL, passing key/value parameters to a Web Service that outputs to MySQL.</p>
<p>On with the code, starting with the &#8220;Web Service&#8221;. What follow is a mere Perl script, useful for testing. Depending on the expected load, you may want to use a proper application server, providing MySQL DB <a href="http://en.wikipedia.org/wiki/Connection_pool">connection pooling</a>. What you should <i>really</i> do, is serve the script through HTTPS and password protect it. Without SSL, a malicious user could sniff the cleartext requests sent by the source DB, forge similar ones and litter/DOS the MySQL instance. Of course, the Web Service could output to just any supported DB, not only to MySQL.</p>
<div class="codecolorer-container perl blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;height:300px;"><div class="perl codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">#!/usr/bin/perl</span><br />
<br />
<span style="color: #000000; font-weight: bold;">use</span> DBI<span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">use</span> CGI<span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">use</span> strict<span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$DEBUG</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">@FIELDS</span> <span style="color: #339933;">=</span> <a href="http://perldoc.perl.org/functions/qw.html"><span style="color: #000066;">qw</span></a><span style="color: #009900;">&#40;</span><br />
CallId<br />
OriginationNumber<br />
CalledNumber<br />
DestinationNumber<br />
StartTime<br />
ScriptConnectTime<br />
DeliveredTime<br />
ConnectTime<br />
TransferTime<br />
EndTime<br />
DisconnectReason<br />
TransferredToCallId<br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$q</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> CGI<span style="color: #339933;">;</span><br />
<a href="http://perldoc.perl.org/functions/print.html"><span style="color: #000066;">print</span></a> <span style="color: #0000ff;">$q</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">header</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">-</span>type <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'text/plain'</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span>charset <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'ISO-8859-1'</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span>expires <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'-1d'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># checks</span><br />
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$checkresult</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$checkmessage</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">''</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">sub</span> setcheck <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$$</span><span style="color: #0000ff;">$$</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">my</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$rrc</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$rc</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$rrs</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$rs</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">@_</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">$$rrc</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$rc</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">$$rrs</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$rs</span><span style="color: #339933;">;</span>&nbsp; &nbsp; <br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #000000; font-weight: bold;">sub</span> isnumber <span style="color: #009900;">&#123;</span> <a href="http://perldoc.perl.org/functions/return.html"><span style="color: #000066;">return</span></a> <span style="color: #cc66cc;">1</span> <span style="color: #b1b100;">if</span> <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^[0-9]*$/i</span><span style="color: #339933;">;</span> <a href="http://perldoc.perl.org/functions/return.html"><span style="color: #000066;">return</span></a> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><br />
<span style="color: #000000; font-weight: bold;">sub</span> issane <span style="color: #009900;">&#123;</span> <a href="http://perldoc.perl.org/functions/return.html"><span style="color: #000066;">return</span></a> <span style="color: #cc66cc;">1</span> <span style="color: #b1b100;">if</span> <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^[a-z0-9%:\- ]*$/i</span><span style="color: #339933;">;</span> <a href="http://perldoc.perl.org/functions/return.html"><span style="color: #000066;">return</span></a> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><br />
setcheck<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">\$checkresult</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span><span style="color: #0000ff;">\$checkmessage</span><span style="color: #339933;">,</span><span style="color: #ff0000;">'NULL CallId'</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">if</span> <span style="color: #0000ff;">$checkresult</span> <span style="color: #b1b100;">and</span> <span style="color: #b1b100;">not</span> <span style="color: #0000ff;">$q</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">param</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">'CallId'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
setcheck<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">\$checkresult</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span><span style="color: #0000ff;">\$checkmessage</span><span style="color: #339933;">,</span><span style="color: #ff0000;">'CallId must be a number'</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">if</span> <span style="color: #0000ff;">$checkresult</span> <span style="color: #b1b100;">and</span> <span style="color: #b1b100;">not</span> isnumber<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$q</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">param</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">'CallId'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">@FIELDS</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; setcheck<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">\$checkresult</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span><span style="color: #0000ff;">\$checkmessage</span><span style="color: #339933;">,</span><span style="color: #ff0000;">&quot;$_ value contains invalid characters&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #0000ff;">$checkresult</span> <span style="color: #b1b100;">and</span> <span style="color: #b1b100;">not</span> issane<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$q</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">param</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$checkresult</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$dbh</span> <span style="color: #339933;">=</span> DBI<span style="color: #339933;">-&gt;</span><span style="color: #006600;">connect</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">'DBI:mysql:database=dbname'</span><span style="color: #339933;">,</span><span style="color: #ff0000;">'dbuser'</span><span style="color: #339933;">,</span><span style="color: #ff0000;">'password'</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">or</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><a href="http://perldoc.perl.org/functions/print.html"><span style="color: #000066;">print</span></a> <span style="color: #ff0000;">&quot;KO: Error $DBI::err - $DBI::errstr<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <a href="http://perldoc.perl.org/functions/exit.html"><span style="color: #000066;">exit</span></a><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$values</span> <span style="color: #339933;">=</span> <a href="http://perldoc.perl.org/functions/join.html"><span style="color: #000066;">join</span></a> <span style="color: #ff0000;">','</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span> <a href="http://perldoc.perl.org/functions/map.html"><span style="color: #000066;">map</span></a> <span style="color: #009900;">&#123;</span> <span style="color: #0000ff;">$dbh</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">quote</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">$q</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">param</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> <span style="color: #0000ff;">$q</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">param</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #ff0000;">''</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#125;</span> <span style="color: #0000ff;">@FIELDS</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$sth</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$dbh</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">prepare</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;INSERT INTO callslog VALUES ($values)&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">or</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><a href="http://perldoc.perl.org/functions/print.html"><span style="color: #000066;">print</span></a> <span style="color: #ff0000;">&quot;KO: Error $DBI::err - $DBI::errstr<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <a href="http://perldoc.perl.org/functions/exit.html"><span style="color: #000066;">exit</span></a><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">$sth</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">execute</span> <span style="color: #b1b100;">or</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><a href="http://perldoc.perl.org/functions/print.html"><span style="color: #000066;">print</span></a> <span style="color: #ff0000;">&quot;KO: Error $DBI::err - $DBI::errstr<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <a href="http://perldoc.perl.org/functions/exit.html"><span style="color: #000066;">exit</span></a><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$DEBUG</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span style="color: #000066;">print</span></a> <span style="color: #0000ff;">$_</span><span style="color: #339933;">.</span><span style="color: #ff0000;">': '</span><span style="color: #339933;">.</span><span style="color: #0000ff;">$q</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">param</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #b1b100;">for</span> <span style="color: #0000ff;">@FIELDS</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span style="color: #000066;">print</span></a> <span style="color: #ff0000;">&quot;OK<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span style="color: #000066;">print</span></a> <span style="color: #ff0000;">&quot;KO: $checkmessage<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<a href="http://perldoc.perl.org/functions/exit.html"><span style="color: #000066;">exit</span></a><span style="color: #339933;">;</span></div></div>
<p>Next, the trigger code. It acts after each INSERT on the IpPbxCDR table. If a called number ends with the given digits, calls the Stored Procedure <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">spLogCall</span>, passing it the fields we&#8217;re interested in. I use the (commented) <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">raiserror</span>  call for debugging purposes.</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;height:300px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">USE</span> <span style="color: #66cc66;">&#91;</span>ippbxlog<span style="color: #66cc66;">&#93;</span><br />
GO<br />
<span style="color: #993333; font-weight: bold;">SET</span> ANSI_NULLS <span style="color: #993333; font-weight: bold;">ON</span><br />
GO<br />
<span style="color: #993333; font-weight: bold;">SET</span> QUOTED_IDENTIFIER <span style="color: #993333; font-weight: bold;">ON</span><br />
GO<br />
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TRIGGER</span> <span style="color: #66cc66;">&#91;</span>dbo<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#91;</span>tr_ProcessCall<span style="color: #66cc66;">&#93;</span><br />
<span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #66cc66;">&#91;</span>dbo<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#91;</span>IpPbxCDR<span style="color: #66cc66;">&#93;</span><br />
AFTER <span style="color: #993333; font-weight: bold;">INSERT</span><br />
<span style="color: #993333; font-weight: bold;">AS</span><br />
BEGIN<br />
&nbsp; &nbsp; DECLARE<br />
&nbsp; &nbsp; &nbsp; &nbsp; @RightMatch nvarchar <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @CallId int<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @OriginationNumber nvarchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @CalledNumber nvarchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @DestinationNumber nvarchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @StartTime datetime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @ScriptConnectTime datetime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @DeliveredTime datetime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @ConnectTime datetime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @TransferTime datetime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @EndTime datetime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @DisconnectReason nvarchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @TransferredToCallId int<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SET</span> @RightMatch <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'12345678'</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @CallId <span style="color: #66cc66;">=</span> CallId<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @OriginationNumber <span style="color: #66cc66;">=</span> OriginationNumber<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @CalledNumber <span style="color: #66cc66;">=</span> CalledNumber<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @DestinationNumber <span style="color: #66cc66;">=</span> DestinationNumber<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @StartTime <span style="color: #66cc66;">=</span> StartTime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @ScriptConnectTime <span style="color: #66cc66;">=</span> ScriptConnectTime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @DeliveredTime <span style="color: #66cc66;">=</span> DeliveredTime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @ConnectTime <span style="color: #66cc66;">=</span> ConnectTime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @TransferTime <span style="color: #66cc66;">=</span> TransferTime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @EndTime <span style="color: #66cc66;">=</span> EndTime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @DisconnectReason <span style="color: #66cc66;">=</span> DisconnectReason<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @TransferredToCallId <span style="color: #66cc66;">=</span> TransferredToCallId<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> INSERTED<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">RIGHT</span><span style="color: #66cc66;">&#40;</span>@DestinationNumber<span style="color: #66cc66;">,</span>LEN<span style="color: #66cc66;">&#40;</span>@RightMatch<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> @RightMatch<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">RIGHT</span><span style="color: #66cc66;">&#40;</span>@CalledNumber<span style="color: #66cc66;">,</span>LEN<span style="color: #66cc66;">&#40;</span>@RightMatch<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> @RightMatch<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; BEGIN<br />
<span style="color: #808080; font-style: italic;">--raiserror('%s',16,1, @DestinationNumber)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; EXEC spLogCall<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @CallId<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @OriginationNumber<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @CalledNumber<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @DestinationNumber<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @StartTime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @ScriptConnectTime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @DeliveredTime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @ConnectTime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @TransferTime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @EndTime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @DisconnectReason<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @TransferredToCallId<br />
&nbsp; &nbsp; END<br />
END</div></div>
<p>Lastly, the Web Service contacting Stored Procedure. I use <a href="http://msdn.microsoft.com/en-us/library/ms189763.aspx"><span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">sp_OACreate</span></a> to create an OLE object of class <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">MSXML2.ServerXMLHTTP</span> passing it the contructed GET URL (address + parameters). Depending on MS SQL&#8217;s version, you may have to explicitly enable in-database OLE automation, this way:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">exec sp_configure 'show advanced options', 1<br />
go<br />
reconfigure<br />
go<br />
exec sp_configure 'Ole Automation Procedures', 1<br />
go<br />
reconfigure<br />
go</div></div>
<p>Timeouts for various operations are set to reasonably low values, we don&#8217;t want the DB to &#8220;block&#8221; for too long. And again: <i>use HTTPS</i>. Get your certificates right (on MS SQL&#8217;s server, install the root certificate for the CA who issued the cert you&#8217;re using on the web/application server) and use HTTPS.</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;height:300px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">USE</span> <span style="color: #66cc66;">&#91;</span>ippbxlog<span style="color: #66cc66;">&#93;</span><br />
GO<br />
<span style="color: #993333; font-weight: bold;">SET</span> ANSI_NULLS <span style="color: #993333; font-weight: bold;">ON</span><br />
GO<br />
<span style="color: #993333; font-weight: bold;">SET</span> QUOTED_IDENTIFIER <span style="color: #993333; font-weight: bold;">ON</span><br />
GO<br />
<br />
<span style="color: #993333; font-weight: bold;">CREATE</span> PROCEDURE <span style="color: #66cc66;">&#91;</span>dbo<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#91;</span>spLogCall<span style="color: #66cc66;">&#93;</span> <br />
&nbsp; &nbsp; @CallId int<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; @OriginationNumber nvarchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; @CalledNumber nvarchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; @DestinationNumber nvarchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; @StartTime datetime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; @ScriptConnectTime datetime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; @DeliveredTime datetime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; @ConnectTime datetime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; @TransferTime datetime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; @EndTime datetime<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; @DisconnectReason nvarchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; @TransferredToCallId int<br />
<span style="color: #993333; font-weight: bold;">AS</span><br />
<br />
BEGIN<br />
DECLARE <br />
&nbsp; &nbsp; @Object int<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; @hr int<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; @openparams nvarchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2048</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; @responsetext varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">8000</span><span style="color: #66cc66;">&#41;</span>;<br />
<br />
EXEC @hr <span style="color: #66cc66;">=</span> sp_OACreate <span style="color: #ff0000;">'MSXML2.ServerXMLHTTP'</span><span style="color: #66cc66;">,</span> @Object out<br />
<span style="color: #993333; font-weight: bold;">IF</span> @hr <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span><br />
BEGIN<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SET</span> CONCAT_NULL_YIELDS_NULL OFF<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SET</span> @openparams <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'open(&quot;GET&quot;, &quot;http://10.1.1.123/ws/CDR.pl?'</span> <span style="color: #66cc66;">+</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">'CallId='</span> <span style="color: #66cc66;">+</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CAST<span style="color: #66cc66;">&#40;</span>@CallId <span style="color: #993333; font-weight: bold;">AS</span> varchar<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #ff0000;">'&amp;'</span> <span style="color: #66cc66;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">'OriginationNumber='</span> <span style="color: #66cc66;">+</span> &nbsp; &nbsp;CAST<span style="color: #66cc66;">&#40;</span>@OriginationNumber <span style="color: #993333; font-weight: bold;">AS</span> varchar<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #ff0000;">'&amp;'</span> <span style="color: #66cc66;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">'CalledNumber='</span> <span style="color: #66cc66;">+</span> &nbsp; &nbsp; &nbsp; &nbsp; CAST<span style="color: #66cc66;">&#40;</span>@CalledNumber <span style="color: #993333; font-weight: bold;">AS</span> varchar<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #ff0000;">'&amp;'</span> <span style="color: #66cc66;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">'DestinationNumber='</span> <span style="color: #66cc66;">+</span> &nbsp; &nbsp;CAST<span style="color: #66cc66;">&#40;</span>@DestinationNumber <span style="color: #993333; font-weight: bold;">AS</span> varchar<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #ff0000;">'&amp;'</span> <span style="color: #66cc66;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">'StartTime='</span> <span style="color: #66cc66;">+</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CONVERT<span style="color: #66cc66;">&#40;</span>varchar<span style="color: #66cc66;">,</span> @StartTime<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">120</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #ff0000;">'&amp;'</span> <span style="color: #66cc66;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">'ScriptConnectTime='</span> <span style="color: #66cc66;">+</span> &nbsp; &nbsp;CONVERT<span style="color: #66cc66;">&#40;</span>varchar<span style="color: #66cc66;">,</span> @ScriptConnectTime<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">120</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #ff0000;">'&amp;'</span> <span style="color: #66cc66;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">'DeliveredTime='</span> <span style="color: #66cc66;">+</span> &nbsp; &nbsp; &nbsp; &nbsp;CONVERT<span style="color: #66cc66;">&#40;</span>varchar<span style="color: #66cc66;">,</span> @DeliveredTime<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">120</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #ff0000;">'&amp;'</span> <span style="color: #66cc66;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">'ConnectTime='</span> <span style="color: #66cc66;">+</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CONVERT<span style="color: #66cc66;">&#40;</span>varchar<span style="color: #66cc66;">,</span> @ConnectTime<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">120</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #ff0000;">'&amp;'</span> <span style="color: #66cc66;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">'TransferTime='</span> <span style="color: #66cc66;">+</span> &nbsp; &nbsp; &nbsp; &nbsp; CONVERT<span style="color: #66cc66;">&#40;</span>varchar<span style="color: #66cc66;">,</span> @TransferTime<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">120</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #ff0000;">'&amp;'</span> <span style="color: #66cc66;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">'EndTime='</span> <span style="color: #66cc66;">+</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CONVERT<span style="color: #66cc66;">&#40;</span>varchar<span style="color: #66cc66;">,</span> @EndTime<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">120</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #ff0000;">'&amp;'</span> <span style="color: #66cc66;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">'DisconnectReason='</span> <span style="color: #66cc66;">+</span> &nbsp; &nbsp; CAST<span style="color: #66cc66;">&#40;</span>@DisconnectReason <span style="color: #993333; font-weight: bold;">AS</span> varchar<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #ff0000;">'&amp;'</span> <span style="color: #66cc66;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">'TransferredToCallId='</span> <span style="color: #66cc66;">+</span> &nbsp;CAST<span style="color: #66cc66;">&#40;</span>@TransferredToCallId <span style="color: #993333; font-weight: bold;">AS</span> varchar<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">'&quot;, False)'</span><br />
&nbsp; &nbsp; EXEC @hr <span style="color: #66cc66;">=</span> sp_OAMethod @Object<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'setTimeouts(3000,3000,3000,3000)'</span><br />
&nbsp; &nbsp; EXEC @hr <span style="color: #66cc66;">=</span> sp_OAMethod @Object<span style="color: #66cc66;">,</span> @openparams<br />
&nbsp; &nbsp; EXEC @hr <span style="color: #66cc66;">=</span> sp_OAMethod @Object<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Send'</span><br />
&nbsp; &nbsp; EXEC @hr <span style="color: #66cc66;">=</span> sp_OAGetProperty @Object<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'responseText'</span><span style="color: #66cc66;">,</span> @responseText out<br />
END<br />
END</div></div>
<p>That&#8217;s it, the method performs and scales quite well. I think I&#8217;ll find other uses for it soon&#8230;
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-556-1'>The operation could not be performed because OLE DB provider &#8220;%ls&#8221; for linked server &#8220;%ls&#8221; was unable to begin a distributed transaction. <span class='footnotereverse'><a href='#fnref-556-1'>&#8617;</a></span></li>
</ol>
</div>
 <img src="http://www.108.bz/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=556" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.108.bz/posts/it/from-ms-sql-to-mysql-realtime-row-copy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Recovering NTBackup Tapes</title>
		<link>http://www.108.bz/posts/it/recovering-ntbackup-tapes/</link>
		<comments>http://www.108.bz/posts/it/recovering-ntbackup-tapes/#comments</comments>
		<pubDate>Wed, 25 Aug 2010 10:36:43 +0000</pubDate>
		<dc:creator>Giuliano</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Backup]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Recovery]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.108.bz/?p=539</guid>
		<description><![CDATA[This article will show you how to handle tape backups generated by NTBackup, turn them into a .BKF file (using Linux) and extract specific files (using Linux/Windows). Some of the stuff explained here may also be useful when dealing with corrupt tapes/files, and may work for any backup software that generates MTF (Microsoft Tape Format) [...]]]></description>
			<content:encoded><![CDATA[<p>This article will show you how to handle tape backups generated by <a href="http://en.wikipedia.org/wiki/Ntbackup">NTBackup</a>, turn them into a .BKF file (using Linux) and extract specific files (using Linux/Windows). Some of the stuff explained here may also be useful when dealing with corrupt tapes/files, and may work for any backup software that generates MTF (Microsoft Tape Format) output, such as maybe Symantec Backup Exec<sup class='footnote'><a href='#fn-539-1' id='fnref-539-1'>1</a></sup>.</p>
<p>The scenario: an old machine (hosting a not so important app) crashes badly due to multiple disk failures. O.S. (Windows 2000 Server) won&#8217;t boot anymore. Backups were directed to a local <a href="http://en.wikipedia.org/wiki/Digital_Data_Storage">DDS</a> tape drive, the only one of its kind surviving in the whole Company. While reinstalling the app to another server, I need to recover some files and have access to the pre-crash registry.</p>
<p>And here&#8217;s the plan:</p>
<ul>
<li>Boot the half-dead server with the invaluable <a href="http://www.sysresccd.org/Main_Page">SystemRescueCd</a>.</li>
<li>Put the last available tape backup in the drive.</li>
<li>Save an <i>image</i> of the tape somewhere.</li>
<li>Extract stuff from the image.</li>
</ul>
<p>When SystemRescueCd is running and network connected, make available a shared folder:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root@sysresccd /root % mkdir /mnt/storagespace<br />
root@sysresccd /root % mount -t cifs //fileserver/e$ /mnt/storagespace -o username=administrator,workgroup=domain.local</div></div>
<p>Then, generate the image. NTBackup tape backups are spread across multiple &#8220;tape files&#8221;. If you read the tape from the beginning, sooner or later you will hit EOF (an end-of-file condition). <i>Don&#8217;t</i> rewind it: go on to the next file instead. Repeat until there are no more files to read.<br />
On Unix, the first SCSI tape device is mapped to <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">/dev/st0</span> <i>and</i> <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">/dev/nst0</span>. When a process finishes reading from <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">/dev/st0</span>, the tape is implicitly rewound. Viceversa, using <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">/dev/nst0</span> doesn&#8217;t cause any rewind; tape will stay positioned right after the last block read.</p>
<p>Just in case, perform a manual rewind:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root@sysresccd /mnt/storagespace/temp % mt -f /dev/st0 rewind</div></div>
<p>Then, try to guess the right block size. It seems to be set at 16K. Should this method fail, check the &#8220;How do I find out tape block size?&#8221; method <a href="http://www.cyberciti.biz/faq/rhel-centos-debian-set-tape-blocksize/">here</a>.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root@sysresccd /mnt/storagespace/temp % mt -f /dev/st0 status<br />
SCSI 2 tape drive: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
File number=0, block number=0, partition=0.<br />
Tape block size 16384 bytes. Density code 0x26 (DDS-4 or QIC-4GB).<br />
Soft error count since last status=0<br />
General status bits on (41010000):<br />
&nbsp;BOT ONLINE IM_REP_EN</div></div>
<p>Start reading (by means of <a href="http://en.wikipedia.org/wiki/Dd_(Unix)">dd</a>) with the specified block size. See? We&#8217;re using the non-rewinding tape device <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">/dev/nst0</span>.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">root@sysresccd /mnt/storagespace/temp % for f in `seq 1 10`; do echo dd if=/dev/nst0 of=tapeblock`printf &quot;%<br />
06g&quot; $f`.bin ibs=16384; done<br />
dd if=/dev/nst0 of=tapeblock000001.bin ibs=16384<br />
dd if=/dev/nst0 of=tapeblock000002.bin ibs=16384<br />
dd if=/dev/nst0 of=tapeblock000003.bin ibs=16384<br />
dd if=/dev/nst0 of=tapeblock000004.bin ibs=16384<br />
dd if=/dev/nst0 of=tapeblock000005.bin ibs=16384<br />
dd if=/dev/nst0 of=tapeblock000006.bin ibs=16384<br />
dd if=/dev/nst0 of=tapeblock000007.bin ibs=16384<br />
dd if=/dev/nst0 of=tapeblock000008.bin ibs=16384<br />
dd if=/dev/nst0 of=tapeblock000009.bin ibs=16384<br />
dd if=/dev/nst0 of=tapeblock000010.bin ibs=16384<br />
root@sysresccd /mnt/storagespace/temp % dd if=/dev/nst0 of=tapeblock000001.bin ibs=16384<br />
1+0 records in<br />
32+0 records out<br />
16384 bytes (16 kB) copied, 0.0341089 s, 480 kB/s<br />
root@sysresccd /mnt/storagespace/temp % dd if=/dev/nst0 of=tapeblock000002.bin ibs=16384<br />
270540+0 records in<br />
8657280+0 records out<br />
4432527360 bytes (4.4 GB) copied, 7666.22 s, 578 kB/s<br />
[..]<br />
root@sysresccd /mnt/storagespace/temp % dd if=/dev/nst0 of=tapeblock000007.bin ibs=16384<br />
4+0 records in<br />
128+0 records out<br />
65536 bytes (66 kB) copied, 0.1176 s, 557 kB/s<br />
root@sysresccd /mnt/storagespace/temp % dd if=/dev/nst0 of=tapeblock000008.bin ibs=16384<br />
0+0 records in<br />
0+0 records out<br />
0 bytes (0 B) copied, 0.00461986 s, 0.0 kB/s<br />
root@sysresccd /mnt/storagespace/temp % dd if=/dev/nst0 of=tapeblock000009.bin ibs=16384<br />
dd: reading `/dev/nst0': Input/output error<br />
0+0 records in<br />
0+0 records out<br />
0 bytes (0 B) copied, 0.00356835 s, 0.0 kB/s</div></div>
<p>Reads beyond the last file will result in an &#8220;Input/output error&#8221;.</p>
<p><a href="http://www.108.bz/wp-content/uploads/2010/08/tape1.png"><img src="http://www.108.bz/wp-content/uploads/2010/08/tape1-300x120.png" alt="Tape image chunks" title="Tape image chunks" width="300" height="120" class="alignnone size-medium wp-image-551" /></a></p>
<p>It&#8217;s time to join the <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">.bin</span> files into a single one: the tape image (maybe using <a href="http://www.freebyte.com/hjsplit/">HJSplit</a> for the task). You could&#8217;ve been more clever than me and appended <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">dd</span>&#8216;s output to a single file, thus skipping the join step and saving space. I didn&#8217;t do it because I wanted to see if any tape file was corrupted (and be able to re-read it, if needed).</p>
<p>I called the tape image &#8220;backup.bkf&#8221;, even though it&#8217;s not a true <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">.BKF</span> file&#8230; As we said, it&#8217;s a tape image. NTBackup is not able to read it, whereas the abundance of &#8220;BKF recovery&#8221; software can. Before going on, let me polemicize a bit. There are many, almost identical, software of this kind. I&#8217;ve got the feeling that they all &#8220;borrow&#8221; from <a href="http://www.codeproject.com/KB/files/BackupReader.aspx">this</a> open source BKF reader<sup class='footnote'><a href='#fn-539-2' id='fnref-539-2'>2</a></sup>. Looks like different commercial developers grabbed the same source, embellished the GUI just a bit, and made a product to sell. How lame. But it turns out that you don&#8217;t need to pay a cent to extract files from a .BKF or tape image, on Linux or Windows as well.</p>
<p>On windows, get <a href="http://www.fpns.net/willy/msbackup.htm">ntbkup</a> by William T. Kranz . I use the (optional) <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">-s3</span> switch to target set 3 which I know holds the System State.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">C:\temp\x&gt;..\ntbkup.exe ..\backup.bkf -s3 -l&quot;\Registry:&quot;<br />
<br />
NTBKUP Ver 1.07c compiled for WIN32 with MAX_PATH = 100<br />
&nbsp; &nbsp;compiled for 64 bit file offsets<br />
Copyright (C) 2003 William T. Kranz<br />
NTBKUP comes with ABSOLUTELY NO WARRANTY<br />
Free software distributed under the terms of the GNU General Public license<br />
See http://www.gnu.org/licenses/gpl.html for license information<br />
Check http://www.fpns.net/willy/msbackup.htm for Updates &amp; Documentation<br />
<br />
resrict operations to backup set 3<br />
device name: C:<br />
volume name: Local disk<br />
device name: D:<br />
volume name: Volume<br />
Set 3:<br />
Name: Company lun-29-06-2009-23.04<br />
Description:<br />
User: DOMAIN\administrator<br />
<br />
device name: System state data from 0x36113d956 to 0x3611ec956<br />
length 716800 &nbsp;atrib 0x20 &nbsp;05/14/2008 &nbsp;03:10:38 PM<br />
extracing: default:<br />
&nbsp;data from 0x3611ecd4e to 0x3611f2d4e<br />
length &nbsp;24576 &nbsp;atrib 0x20 &nbsp;06/29/2009 &nbsp;09:42:50 PM<br />
extracing: SAM:<br />
&nbsp;data from 0x3611f3156 to 0x3611fe156<br />
length &nbsp;45056 &nbsp;atrib 0x20 &nbsp;06/29/2009 &nbsp;11:00:07 PM<br />
extracing: SECURITY:<br />
&nbsp;data from 0x3611fe556 to 0x3621cb556<br />
length 16568320 &nbsp;atrib 0x20 &nbsp;06/30/2009 &nbsp;01:35:59 AM<br />
extracing: software:<br />
&nbsp;data from 0x3621cb952 to 0x362487952<br />
length 2867200 &nbsp;atrib 0x20 &nbsp;06/29/2009 &nbsp;10:42:23 PM<br />
extracing: system:<br />
&nbsp;data from 0x362487d2e to 0x3624aad2e<br />
length 143360 &nbsp;atrib 0x20 &nbsp;06/04/2003 &nbsp;01:24:14 PM<br />
extracing: userdiff:</div></div>
<p>Bingo, I can load the <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">software</span> hive with &#8220;reg load&#8221; (see <a href="http://www.petri.co.il/reg_command_in_windows_xp.htm">here</a>) and extract the keys I need.</p>
<p>Should you prefer so, download <a href="http://gpl.internetconnection.net/files/mtftar.tar.gz">mtftar</a> on your Linux box, compile it and run something like:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">./mtftar -f /mnt/storagespace/temp/backup.bkf | tar xvf - &quot;Registry&quot;</div></div>
<p>Extract the other files you need and voilà&#8230;
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-539-1'>ex Veritas Backup Exec <span class='footnotereverse'><a href='#fnref-539-1'>&#8617;</a></span></li>
<li id='fn-539-2'>There&#8217;s no executable in the archive. You need Visual Studio and compile it for yourself. <span class='footnotereverse'><a href='#fnref-539-2'>&#8617;</a></span></li>
</ol>
</div>
 <img src="http://www.108.bz/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=539" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.108.bz/posts/it/recovering-ntbackup-tapes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FortiGate firewall clusters group-id</title>
		<link>http://www.108.bz/posts/it/fortigate-firewall-clusters-group-id/</link>
		<comments>http://www.108.bz/posts/it/fortigate-firewall-clusters-group-id/#comments</comments>
		<pubDate>Sat, 03 Jul 2010 15:53:31 +0000</pubDate>
		<dc:creator>Giuliano</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[FortiGate]]></category>
		<category><![CDATA[HA]]></category>
		<category><![CDATA[High Availability]]></category>
		<category><![CDATA[Networking]]></category>

		<guid isPermaLink="false">http://www.108.bz/?p=527</guid>
		<description><![CDATA[A newly installed FortiGate cluster (a simple two node HA active-passive setup) and some packet loss issues&#8230; Ping from the LAN side to the Internet (or from the firewall itself) resulted in about 20% packet loss, while the other way around (WAN to firewall&#8217;s main public IP) didn&#8217;t work at all. I used the following [...]]]></description>
			<content:encoded><![CDATA[<p>A newly installed FortiGate cluster (a simple two node HA active-passive setup) and some packet loss issues&#8230;<br />
Ping from the LAN side to the Internet (or from the firewall itself) resulted in about 20% packet loss, while the other way around (WAN to firewall&#8217;s main public IP) didn&#8217;t work at all.</p>
<p>I used the following command to check my MAC addresses:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">FORTIGATE-PRI # diagnose hardware deviceinfo nic wan1<br />
[..]<br />
Current_HWaddr &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;00:09:0f:09:00:08<br />
Permanent_HWaddr &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;00:09:0f:d1:be:ef<br />
[..]</div></div>
<p>Then resorted to the &#8220;show mac&#8221; switches facilites (some Cisco, some ProCurve) to know on which network ports that particular MAC lied&#8230; Only to discover that the cluster&#8217;s &#8220;logical&#8221; MAC address (00:09:0f:09:00:08) wasn&#8217;t really located where I expected it to be.<br />
Well, FortiGate&#8217;s MAC addresses <i>aren&#8217;t randomly generated</i>. They have predictable values that depend on the firewall&#8217;s port number. The eight port (or wan1, in my case) will always have a virtual MAC as the one above. What will happen if you have two clusters (as we had) sitting on the same L2 network segment (on the same broadcast domain, that is)? You said MAC address conflict? You&#8217;re right.<br />
The solution is simple, use the <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">group-id</span> directive to tweak the logical MAC address, i.e.:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">config system ha<br />
&nbsp; &nbsp; set group-id 10<br />
end</div></div>
<p>Changes the second right-most bytes of the MAC, from 00 to 0a:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">before &nbsp;00:09:0f:09:00:08<br />
after &nbsp; 00:09:0f:09:0a:08</div></div>
<p>Point is that the &#8220;FortiOS High Availablity <a href="http://docs.fortinet.com/fgt/handbook/fortigate-ha-40-mr2.pdf">Handbook</a>&#8221; explains the case very thoroughly! See page 192, paragraph &#8220;Diagnosing packet loss with two FortiGate HA clusters in the same broadcast domain&#8221;. We&#8217;re so used to discardable product documentation that sometimes we don&#8217;t even try to look for clues where they should normally reside.<br />
Instead of troubleshooting, this time, I should really have Read The (unexpectedly) Fine Manual&#8230; </p>
 <img src="http://www.108.bz/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=527" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.108.bz/posts/it/fortigate-firewall-clusters-group-id/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unknown devices on HP servers</title>
		<link>http://www.108.bz/posts/it/unknown-devices-on-hp-servers/</link>
		<comments>http://www.108.bz/posts/it/unknown-devices-on-hp-servers/#comments</comments>
		<pubDate>Mon, 14 Jun 2010 12:14:51 +0000</pubDate>
		<dc:creator>Giuliano</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[HP]]></category>
		<category><![CDATA[Install]]></category>
		<category><![CDATA[Server]]></category>

		<guid isPermaLink="false">http://www.108.bz/?p=508</guid>
		<description><![CDATA[Following up on the &#8220;Unknown devices on IBM servers&#8221; post, let me talk about a similar situation with HP machines (DL180 G6, in my case). The device that Windows fails to identify is this one: PCI\VEN_8086&#38;DEV_3A22&#38;CC_0106 More info can be found by looking up the IDs in the pci.ids file (as I often do), or [...]]]></description>
			<content:encoded><![CDATA[<p>Following up on the &#8220;Unknown devices on IBM servers&#8221; <a href="http://www.108.bz/posts/it/unknown-devices-on-ibm-servers/">post</a>, let me talk about a similar situation with HP machines (DL180 G6, in my case).</p>
<p>The device that Windows fails to identify is this one:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">PCI\VEN_8086&amp;DEV_3A22&amp;CC_0106</div></div>
<p>More info can be found by looking up the IDs in the <a href="http://pciids.sourceforge.net/pci.ids">pci.ids</a> file (as I often do), or by means of the various &#8220;Unkown Device Identifier&#8221; type of software (e.g. <a href="http://www.zhangduo.com/udi.html">this one</a>). If you have a Linux machine at  hand, such a one-liner may suit you:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># sed -n -e '/^8086/,/3a22/p' /usr/share/misc/pci.ids | sed -n -e '1p;$p'<br />
8086 &nbsp;Intel Corporation<br />
&nbsp; &nbsp; &nbsp; &nbsp; 3a22 &nbsp;82801JI (ICH10 Family) SATA AHCI Controller</div></div>
<p>What&#8217;s missing is an Intel SATA driver; needless to say that you won&#8217;t find it anywere on HP site.<br />
I downloaded and installed the <i>Rapid Storage Technology Driver</i> from Intel&#8217;s web site (<a href="http://downloadcenter.intel.com/Detail_Desc.aspx?agr=Y&#038;DwnldID=15251&#038;lang=eng">here</a>). A 280KB download named &#8220;STOR_all32_f6flpy_9.6.0.1014_PV.zip&#8221; fixed things up for me.<br />
Maybe the proper thing to try would&#8217;ve been the latest (March 2010) <a href="http://h20000.www2.hp.com/bizsupport/TechSupport/SoftwareIndex.jsp?lang=en&#038;cc=us&#038;prodNameId=3716247&#038;prodTypeId=18964&#038;prodSeriesId=3716246&#038;swLang=13&#038;taskId=135&#038;swEnvOID=1005">Proliant Support Pack</a>, but it&#8217;s a big download and I didn&#8217;t have the time. Also, the onboard SATA controller isn&#8217;t really used (the additional SAS RAID is, instead) and I just wanted to get rid of the yellow warning sign in Device Manager.</p>
 <img src="http://www.108.bz/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=508" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.108.bz/posts/it/unknown-devices-on-hp-servers/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>The offline ACU CD</title>
		<link>http://www.108.bz/posts/it/the-offline-acu-cd/</link>
		<comments>http://www.108.bz/posts/it/the-offline-acu-cd/#comments</comments>
		<pubDate>Fri, 28 May 2010 10:03:12 +0000</pubDate>
		<dc:creator>Giuliano</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[FC]]></category>
		<category><![CDATA[Fibre Channel]]></category>
		<category><![CDATA[HP]]></category>

		<guid isPermaLink="false">http://www.108.bz/?p=504</guid>
		<description><![CDATA[Well hidden in their labyrinthian web site, you may stumble upon HP&#8217;s &#8220;Array Configuration Utility (ACU) Offline CD for Smart Array&#8221;. A plain bootable CD, useful when ACU simply can&#8217;t be installed on the server/OS. Example: I needed to tweak SSP (Selective Storage Presentation) settings on an MSA1000, connected through Fiber Channel HBAs (QLogic) to [...]]]></description>
			<content:encoded><![CDATA[<p>Well <a href="http://h20000.www2.hp.com/bizsupport/TechSupport/SoftwareDescription.jsp?lang=en&#038;cc=us&#038;prodTypeId=15351&#038;prodSeriesId=1121516&#038;prodNameId=3288134&#038;swEnvOID=2025&#038;swLang=8&#038;mode=2&#038;taskId=135&#038;swItem=MTX-f0790470403f4da3bd94126308">hidden</a> in their labyrinthian web site, you may stumble upon HP&#8217;s &#8220;Array Configuration Utility (ACU) Offline CD for Smart Array&#8221;. A plain bootable CD, useful when ACU simply can&#8217;t be installed on the server/OS.<br />
Example: I needed to tweak SSP (Selective Storage Presentation) settings on an MSA1000, connected through Fiber Channel HBAs (QLogic) to some rather old HP DL580 G2. The servers were running VMware ESX 3i 3.5.0 build-207095 (the latest one compatibile with those kind of CPUs) with no management agents installed. Since the MSA1000 can only be managed &#8220;in-band&#8221; or via a non standard serial cable the Customer, of course, lost long ago, I rebooted an ESX host with the offline ACU CD&#8230;<br />
Before that, I also tried a standard SmartStart CD, but it didn&#8217;t work. I had version 7.80 (way younger than the servers/HBAs), but no link lights on the FC switch, meaning no firmware loaded on the QLogic card, meaning no SmartStart supported HBA drivers. Offline ACU CD version 8.20.19 worked like a charm instead. Find its latest release by <a href="http://www.google.com/search?hl=en&#038;source=hp&#038;q=site%3Ahp.com+array+configuration+utility">searching</a> &#8220;array configuration utility&#8221; on <a href="http://www.hp.com">hp.com</a>, clicking on &#8220;Download software&#8221;, then &#8220;Linux GUI ACU&#8221;. Download link is somewhere in that page&#8230;</p>
 <img src="http://www.108.bz/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=504" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.108.bz/posts/it/the-offline-acu-cd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using the CLI to manage Windows DNS servers</title>
		<link>http://www.108.bz/posts/uncategorized/using-the-cli-to-manage-windows-dns-servers/</link>
		<comments>http://www.108.bz/posts/uncategorized/using-the-cli-to-manage-windows-dns-servers/#comments</comments>
		<pubDate>Mon, 24 May 2010 14:16:46 +0000</pubDate>
		<dc:creator>Giuliano</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Active Directory]]></category>
		<category><![CDATA[CLI]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[Networking]]></category>

		<guid isPermaLink="false">http://www.108.bz/?p=486</guid>
		<description><![CDATA[(This, for once, is going to be quick.) Did you know about the Dnscmd.exe command? Read about it here and here. It&#8217;s the command-line/DOS prompt way to configure Microsoft&#8217;s DNS servers&#8230; If you need to create many zones/records at once, it saves you lots of clicks. Here&#8217;s how to add six DNS zones (same domain [...]]]></description>
			<content:encoded><![CDATA[<p>(This, for once, is going to be quick.)<br />
Did you know about the <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">Dnscmd.exe</span> command? Read about it <a href="http://technet.microsoft.com/en-us/library/cc778513(WS.10).aspx">here</a> and <a href="http://www.petri.co.il/dnscmd_command_in_windows_2000_2003.htm">here</a>. It&#8217;s the command-line/DOS prompt way to configure Microsoft&#8217;s DNS servers&#8230; If you need to create many zones/records at once, it saves you lots of clicks.<br />
Here&#8217;s how to add six DNS zones (same domain name, different TLD). With the <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">/DSPrimary</span> option, the zone will be stored into Active Directory (rather than a file).</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">dnscmd /ZoneAdd domainname.bz &nbsp;/DSPrimary<br />
dnscmd /ZoneAdd domainname.biz /DSPrimary<br />
dnscmd /ZoneAdd domainname.com /DSPrimary<br />
dnscmd /ZoneAdd domainname.eu &nbsp;/DSPrimary<br />
dnscmd /ZoneAdd domainname.net /DSPrimary<br />
dnscmd /ZoneAdd domainname.org /DSPrimary</div></div>
<p>And here&#8217;s how to add the same &#8220;A&#8221; record (named &#8220;www&#8221;) to each of the zones created above.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">dnscmd dns-dc-hostname /RecordAdd domainname.bz &nbsp;www A 10.0.0.123<br />
dnscmd dns-dc-hostname /RecordAdd domainname.biz www A 10.0.0.123<br />
dnscmd dns-dc-hostname /RecordAdd domainname.com www A 10.0.0.123<br />
dnscmd dns-dc-hostname /RecordAdd domainname.eu &nbsp;www A 10.0.0.123<br />
dnscmd dns-dc-hostname /RecordAdd domainname.net www A 10.0.0.123<br />
dnscmd dns-dc-hostname /RecordAdd domainname.org www A 10.0.0.123</div></div>
<p>As you may have guessed this is the typical scenario where you&#8217;ve got to re-create some external zones, on the internal DNS servers. That&#8217;s needed in order for the internal hosts to reach some server with the &#8220;public&#8221; DNS name, but the private IP.<br />
For the sake of completeness, let me also mention that you could achieve the same effect by leaving DNS as it is, and configuring  &#8220;loopback NAT&#8221;/&#8221;double NAT&#8221; on the router/firewall. E.g.: an internal Host wants to reach an internal Server, given it&#8217;s public hostname, mapped to a public IP address. It asks the (possibly internal) DNS to translate the name. DNS doesn&#8217;t know the zone, it forwards the query to an external DNS Server, obtaining a public IP address that it hands back to the Client. Since its address is non-local, while trying to talk with the Server, the Client sends packets to its default gateway (possibly the router/firewall). The firewall matches the server&#8217;s public IP addresses, substituting it with the right private one. It also changes the source IP, swapping the Client&#8217;s with the firewall&#8217;s LAN address. This way Client and Server are actually communicating <i>through</i> the firewall, even if they&#8217;re both internal hosts. And the Server can&#8217;t tell Client A from Client B since every connection to it comes from the firewall&#8217;s IP address. That&#8217;s the main reason why I prefer duplicating the public DNS zones on internal DNS servers, with private IP addresses: you avoid routing internal traffic through the firewall, and avoid NAT where there shouldn&#8217;t be any.</p>
 <img src="http://www.108.bz/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=486" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.108.bz/posts/uncategorized/using-the-cli-to-manage-windows-dns-servers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bulk unlocking Active Directory user accounts</title>
		<link>http://www.108.bz/posts/it/bulk-unlocking-active-directory-user-accounts/</link>
		<comments>http://www.108.bz/posts/it/bulk-unlocking-active-directory-user-accounts/#comments</comments>
		<pubDate>Sat, 15 May 2010 22:23:59 +0000</pubDate>
		<dc:creator>Giuliano</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Active Directory]]></category>
		<category><![CDATA[LDAP]]></category>
		<category><![CDATA[VBScript]]></category>

		<guid isPermaLink="false">http://www.108.bz/?p=475</guid>
		<description><![CDATA[This post will show you how to generate a list of all the users&#8217; Distinguished Name, then filter it, then do something useful with it. Scenario: saturday morning (after having crashed into bed at 4:00 a.m., btw), Customer calls. A virus hit the Company and one of the most annoying consequences of the outburst, is [...]]]></description>
			<content:encoded><![CDATA[<p>This post will show you how to generate a list of all the users&#8217; <a href="http://en.wikipedia.org/wiki/Distinguished_Name">Distinguished Name</a>, then filter it, then do something useful with it.</p>
<p>Scenario: saturday morning (after having crashed into bed at 4:00 a.m., btw), Customer calls. A virus hit the Company and one of the most annoying consequences of the outburst, is that every domain user account gets locked due to brute-force login attempts (as per the &#8220;Account Lockout Threshold&#8221; <a href="http://technet.microsoft.com/en-us/library/dd277400.aspx">policy</a>). While they run around cleaning PCs and fixing A/V installations<sup class='footnote'><a href='#fn-475-1' id='fnref-475-1'>1</a></sup>, I&#8217;m asked for a method to quickly unlock the accounts.</p>
<p>I tend to carry out these kind of tasks &#8220;the Unix way&#8221;, using the available DOS prompt commands and a bit of VBScript.</p>
<ul>
<li>Start off by calling LDIFDE:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ldifde -r &quot;(objectclass=user)&quot; -l sAMAccountName -m -f users.ldf</div></div>
<p><a href="http://support.microsoft.com/kb/237677">LDIFDE</a> exports/imports Active Directory data to/from properly formatted (<a href="http://en.wikipedia.org/wiki/LDIF">LDIF</a>) text files. I use it a lot. Ran as shown above, LDIFDE exports the objects of class &#8220;user&#8221; into a file named <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">users.ldf</span> . Of the many attributes an LDAP object bears, I tell LDIFDE to output just the &#8220;sAMAccountName&#8221; one. If I hadn&#8217;t specified any attribute, in the resulting file I&#8217;d have found duplicate DNs for the same user. That&#8217;s because of how the resulting LDIF file is described. Some A/D data is &#8220;incrementally&#8221; added to existing objects given their DN. I just picked sAMAccountName because every user has one and, also, to keep the file small.</li>
<li>Then:
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">findstr /I /b dn.*ou=service.users users.ldf &gt; service_users.txt<br />
findstr /I /b dn.*cn=users users.ldf &gt; normal_users.txt</div></div>
<p><a href="http://technet.microsoft.com/en-us/library/bb490907.aspx">findstr</a> is Microsoft&#8217;s &#8220;poor man version&#8221; of <a href="http://en.wikipedia.org/wiki/Grep">grep</a>, supporting a subset of the regular expression everyone has or should&#8217;ve come to love. Here I&#8217;m using it to extract Distinguished Names from the LDIF (only the ones that lie in a given Organizational Unit), and saving them to the <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">*_users.txt</span> files. They will look like:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">dn: CN=squidauth,OU=Service Users,DC=contoso,DC=com<br />
dn: CN=exchangebackup,OU=Service Users,DC=contoso,DC=com<br />
dn: CN=ldap,OU=Service Users,DC=contoso,DC=com<br />
dn: CN=batchcopy,OU=Service Users,DC=contoso,DC=com</div></div>
</li>
<li>Here&#8217;s the VBScript function to unlock an account given its DN:
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Sub</span> unlockuser(userDN)<br />
&nbsp; <span style="color: #000080;">Set</span> objUser = GetObject (<span style="color: #800000;">&quot;LDAP://&quot;</span> &amp; userDN)<br />
&nbsp; objUser.IsAccountLocked = <span style="color: #000080;">False</span><br />
&nbsp; objUser.SetInfo<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span></div></div>
<p>We just need to transform findstr&#8217;s output, substituting the leading &#8220;<span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">dn: </span>&#8221; with &#8220;<span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">unlockuser</span>&#8221; and enclosing in double quotes what follows. At the top of the new, transformed, file, we&#8217;ll copy/paste <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">unlockuser</span> subroutine definition. That&#8217;ll make our final script.</li>
<li>How to carry out the transform? Using this VBS snippet; it processes its <a href="http://en.wikipedia.org/wiki/Standard_input">Standard Input</a> line by line, and outputs the modifications on Standard Output, just like any Unix file filtering command.
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Set</span> StdIn = WScript.StdIn <br />
<span style="color: #000080;">Do</span> <span style="color: #000080;">While</span> <span style="color: #000080;">Not</span> StdIn.AtEndOfStream <br />
&nbsp; &nbsp; <span style="color: #000080;">line</span> = stdin.readline<br />
&nbsp; &nbsp; <span style="color: #000080;">line</span> = right(<span style="color: #000080;">line</span>,len(<span style="color: #000080;">line</span>)-4)<br />
&nbsp; &nbsp; wscript.echo <span style="color: #800000;">&quot;unlockuser &quot;</span><span style="color: #800000;">&quot;&quot;</span> &amp; <span style="color: #000080;">line</span> &amp; <span style="color: #800000;">&quot;&quot;</span><span style="color: #800000;">&quot;&quot;</span><br />
<span style="color: #000080;">Loop</span></div></div>
<p>I saved it in a &#8220;<span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">dnfilter.vbs</span>&#8221; file and used it this way:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">type service_users.txt | cscript /nologo dnfilter.vbs &gt; unlock_service_users.vbs</div></div>
<p>To obtain something like this:</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">unlockuser <span style="color: #800000;">&quot;CN=squidauth,OU=Service Users,DC=contoso,DC=com&quot;</span><br />
unlockuser <span style="color: #800000;">&quot;CN=exchangebackup,OU=Service Users,DC=contoso,DC=com&quot;</span><br />
unlockuser <span style="color: #800000;">&quot;CN=ldap,OU=Service Users,DC=contoso,DC=com&quot;</span><br />
unlockuser <span style="color: #800000;">&quot;CN=batchcopy,OU=Service Users,DC=contoso,DC=com&quot;</span></div></div>
</li>
</ul>
<p>As I said, add the <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">unlockuser</span> function at the top of <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">unlock_service_users.vbs</span> and you&#8217;ll have your bulk unlocking script.
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-475-1'>A/V usefulness is often questionable. At least three times a year an unfortunate Customer gets infected by a 0-day threat&#8230; <img src='http://www.108.bz/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />  <span class='footnotereverse'><a href='#fnref-475-1'>&#8617;</a></span></li>
</ol>
</div>
 <img src="http://www.108.bz/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=475" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.108.bz/posts/it/bulk-unlocking-active-directory-user-accounts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dumping streaming media in 25 lines of Perl</title>
		<link>http://www.108.bz/posts/it/dumping-streaming-media-in-25-lines-of-perl/</link>
		<comments>http://www.108.bz/posts/it/dumping-streaming-media-in-25-lines-of-perl/#comments</comments>
		<pubDate>Thu, 13 May 2010 10:11:23 +0000</pubDate>
		<dc:creator>Giuliano</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Network Protocol Analysis]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Reverse Engineering]]></category>

		<guid isPermaLink="false">http://www.108.bz/?p=459</guid>
		<description><![CDATA[Analysing TCP based protocols often means dealing with TCP sessions (also called streams or flows). A TCP connection, from an application point of view, is much like a bidirectional file descriptor through which ordered data can be read or written. &#8220;On the wire&#8221; though, data is not ordered at all. It is split into packets, [...]]]></description>
			<content:encoded><![CDATA[<p>Analysing TCP based protocols often means dealing with TCP <i>sessions</i> (also called streams or flows).<br />
A TCP connection, from an application point of view, is much like a bidirectional file descriptor through which ordered data can be read or written. &#8220;On the wire&#8221; though, data is not ordered at all. It is split into packets, possibly shuffled and mixed with other traffic. You can capture packets using a sniffer, but to make any sense of them you also need an analyzer tool able to do the reordering/reassembling job. <a href="http://www.wireshark.org">Wireshark</a>, for instance, doubles as a sniffer and an analyzer, backed up by the ubiquitous <a href="http://en.wikipedia.org/wiki/Libpcap">libpcap</a>.</p>
<p>Imagine having dumped/sniffed 1GB worth of traffic. We would like to pinpoint a single TCP session, isolating it from the rest. Here&#8217;s how we could proceed:</p>
<ul>
<li>Identify the source/destination addresses and source/destination ports we&#8217;re interested in. Then throw away any packet that doesn&#8217;t match this tuple. That&#8217;s what Wireshark basically does when you select a packet, right click and hit &#8220;Follow TCP Stream&#8221;. If the same tuple doesn&#8217;t get reused for another, unrelated, session, this method works just fine<sup class='footnote'><a href='#fn-459-1' id='fnref-459-1'>1</a></sup>.</li>
<li>Reorder/reassemble packets.</li>
<li>Extract packets&#8217; payload.</li>
<li>Present the payload in a way that makes sense. That depends on the L7 protocol. HTTP without <a href="http://en.wikipedia.org/wiki/HTTP_persistent_connection">keep-alive</a> is strictly request/response: print what the client sent to the server (outbound traffic) before and then what the server answered (inbound traffic). Other protocols may behave differently and you may choose to separate inbound traffic from outbound, or rely on timing to correctly present the dialogue between peers.</li>
</ul>
<p>Besides Wireshark, there are tools that do just that and can also be automated. See <a href="http://www.wireshark.org/docs/man-pages/tshark.html">TShark</a> or <a href="http://www.circlemud.org/~jelson/software/tcpflow/">tcpflow</a>.</p>
<p>What if you want to script everything and build your own TCP analyzer? Perl&#8217;s module <a href="http://search.cpan.org/search?query=Net%3A%3AAnalysis&#038;mode=module">Net::Analysis</a> is surprisingly convenient for the task. It does the dirty job I described above and presents your code with ready to be processed TCP sessions.</p>
<p>Practical goal: saving MP3 files streamed by <a href="http://grooveshark.com">Grooveshark</a>. Disclaimer: I&#8217;m by no means pushing anyone to illegally download stuff, this is just a working, sensible, instructional example that uses a song freely available anyway (by Revolution Void, check them out <a href="http://www.jamendo.com/en/artist/revolutionvoid/">here</a>, they&#8217;re great).</p>
<p><span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">GroovesharkListener.pm</span> extends <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">Net::Analysis::Listener::HTTP</span>. It sniffs all the traffic from/to port 80 and, as soon as he sees an HTTP response with a content-type of &#8220;audio&#8221;, dumps its content to file and quits. Simple as that.</p>
<p>Put the module some place where Perl can find it and then launch (as root):</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># perl -MNet::Analysis -e main GroovesharkListener 'port 80'<br />
(starting live capture)<br />
/crossdomain.xml<br />
text/xml<br />
/service.php?addSongsToQueueExt<br />
text/html; charset=UTF-8<br />
/static/amazonart/m8c8c9f4291508bca130c1caac2bda75b.png<br />
image/png<br />
[...some more cruft...]<br />
/stream.php<br />
audio/mpeg<br />
Dumping 8481224 bytes to groovesharkgyzBy.mp3 be patient...<br />
<br />
# id3v2 -l groovesharkgyzBy.mp3<br />
id3v1 tag info for groovesharkgyzBy.mp3:<br />
Title &nbsp;: Invisible Walls &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Artist: Revolution Void &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
Album &nbsp;: Increase the Dosage &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Year: 2004, Genre: Other (12)<br />
Comment: http://www.jamendo.com/ &nbsp; &nbsp; &nbsp; &nbsp; Track: 1</div></div>
<p>That&#8217;s it, just one more thing. <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">Net::Analysis</span> doesn&#8217;t allow you to select a specific network interface, it just picks up the first available one. I wrote a small <a href='http://www.108.bz/wp-content/uploads/2010/05/NetAnalysis_device_support_in_live_capture.diff_.txt'>patch</a> to address this shortcoming, it adds a &#8220;<span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">device=</span>&#8221; parameter that you can use this way:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># perl -MNet::Analysis -e main GroovesharkListener,device=wlan1 'port 80'</div></div>
<p>And here&#8217;s what <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">GroovesharkListener.pm</span> looks like:</p>
<div class="codecolorer-container perl blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;height:300px;"><div class="perl codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># choose a song</span><br />
<span style="color: #666666; font-style: italic;"># run (as root or via sudo):</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp; perl -MNet::Analysis -e main GroovesharkListener 'port 80'</span><br />
<span style="color: #666666; font-style: italic;"># click &quot;play&quot; and wait for the file to be dumped...</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- Giuliano - http://www.108.bz</span><br />
<a href="http://perldoc.perl.org/functions/package.html"><span style="color: #000066;">package</span></a> Net<span style="color: #339933;">::</span><span style="color: #006600;">Analysis</span><span style="color: #339933;">::</span><span style="color: #006600;">Listener</span><span style="color: #339933;">::</span><span style="color: #006600;">GroovesharkListener</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">use</span> strict<span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">use</span> base <a href="http://perldoc.perl.org/functions/qw.html"><span style="color: #000066;">qw</span></a><span style="color: #009900;">&#40;</span>Net<span style="color: #339933;">::</span><span style="color: #006600;">Analysis</span><span style="color: #339933;">::</span><span style="color: #006600;">Listener</span><span style="color: #339933;">::</span><span style="color: #006600;">HTTP</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">use</span> File<span style="color: #339933;">::</span><span style="color: #006600;">Temp</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">sub</span> http_transaction <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">my</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$self</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$args</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">@_</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">my</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$http_req</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$args</span><span style="color: #339933;">-&gt;</span><span style="color: #009900;">&#123;</span>req<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span> <br />
&nbsp; &nbsp; <span style="color: #b1b100;">my</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$http_resp</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$args</span><span style="color: #339933;">-&gt;</span><span style="color: #009900;">&#123;</span>resp<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span> <br />
<br />
&nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span style="color: #000066;">print</span></a> <span style="color: #0000ff;">$http_req</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">uri</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$content_type</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$http_resp</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">header</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">'Content-Type'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span style="color: #000066;">print</span></a> <span style="color: #ff0000;">&quot;$content_type<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$content_type</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/audio/i</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$fh</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> File<span style="color: #339933;">::</span><span style="color: #006600;">Temp</span><span style="color: #009900;">&#40;</span>TEMPLATE <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'groovesharkXXXXX'</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SUFFIX &nbsp; <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'.mp3'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; UNLINK &nbsp; <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span style="color: #000066;">print</span></a> <span style="color: #ff0000;">&quot;Dumping &quot;</span><span style="color: #339933;">.</span><a href="http://perldoc.perl.org/functions/length.html"><span style="color: #000066;">length</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$http_resp</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">content</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #ff0000;">&quot; bytes to &quot;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">$fh</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">filename</span><span style="color: #339933;">.</span><span style="color: #ff0000;">&quot; be patient...<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/print.html"><span style="color: #000066;">print</span></a> <span style="color: #0000ff;">$fh</span> <span style="color: #0000ff;">$http_resp</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">content</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://perldoc.perl.org/functions/exit.html"><span style="color: #000066;">exit</span></a><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span></div></div>
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-459-1'>newer Wireshark(s) use the &#8220;tcp.stream eq <i>x</i>&#8221; primitive <span class='footnotereverse'><a href='#fnref-459-1'>&#8617;</a></span></li>
</ol>
</div>
 <img src="http://www.108.bz/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=459" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.108.bz/posts/it/dumping-streaming-media-in-25-lines-of-perl/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Active Directory Graphs</title>
		<link>http://www.108.bz/posts/it/active-directory-graphs/</link>
		<comments>http://www.108.bz/posts/it/active-directory-graphs/#comments</comments>
		<pubDate>Wed, 28 Apr 2010 15:26:32 +0000</pubDate>
		<dc:creator>Giuliano</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Active Directory]]></category>
		<category><![CDATA[Graphs]]></category>
		<category><![CDATA[VBS]]></category>

		<guid isPermaLink="false">http://www.108.bz/?p=443</guid>
		<description><![CDATA[Domain Controllers replicate Active Directory data with each other. They do so through Connections that are partly generated by the KCC (Knowledge Consistency Checker), partly configured by you: the Sysadmin . Each connection is one-way. If you open Active Directory Sites and Services, expand a Site and then a Server node, you&#8217;ll notice that Connections [...]]]></description>
			<content:encoded><![CDATA[<p>Domain Controllers replicate Active Directory data with each other. They do so through <i>Connections</i> that are partly generated by the <i>KCC</i> (Knowledge Consistency Checker), partly configured by you: the Sysadmin . Each connection is one-way. If you open <i>Active Directory Sites and Services</i>, expand a Site and then a Server node, you&#8217;ll notice that Connections listed under <i>NTDS Settings</i> are labeled &#8220;From Server&#8221; and &#8220;From Site&#8221;. In the image below (stolen from <a href="http://technet.microsoft.com/en-us/library/dd277430.aspx">here</a>), the DC named HEIDITEST will replicate AD changes by sending them <i>to</i> MHILLMAN2. The Connection Object is thus defined <i>from</i> HEIDITEST, <i>to</i> MHILLMAN2. You can expect a specular Connection to exist, defined under the <i>NTDS Settings</i> node of HEIDITEST.<br />
<a href="http://www.108.bz/wp-content/uploads/2010/04/adss.gif"><img src="http://www.108.bz/wp-content/uploads/2010/04/adss-300x135.gif" alt="" title="Active Directory Sites and Services" width="300" height="135" class="alignnone size-medium wp-image-452" /></a><br />
See <a href="http://technet.microsoft.com/en-us/library/dd277429.aspx">Active Directory Replication</a> for a more in-depth explanation.<br />
Besides Connection objects automatically created by the <i>KCC</i>, which does its best to build a proper replication topology, you sometimes add your own for fault/link tolerance or other reasons. If the domain is sufficiently big, things may become messy. Instead of fumbling my way through <i>Active Directory Sites and Services</i> I wanted to automatically generate a visual representation of such topology, with DCs and Connections: time to write yet another script. </p>
<p>This time I chose VBS over Perl, hoping that this post would be more &#8220;instructional&#8221;. Perl on Windows is not so common, while VBScript is the standard way to automate stuff on that O.S. (despite the language being incredibly clumsy and annoying<sup class='footnote'><a href='#fn-443-1' id='fnref-443-1'>1</a></sup>).</p>
<p>As for the graph format, I chose to output <a href="http://www.graphviz.org/">Graphviz</a> <a href="http://www.graphviz.org/doc/info/lang.html">DOT</a> format/language.</p>
<p>The script works this way:</p>
<ul>
<li>Find the current domain.</li>
<li>Find all the Domain Controllers (AD objects of class <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">nTDSDSA</span>, see <a href="http://blogs.technet.com/heyscriptingguy/archive/2004/12/16/how-can-i-get-a-list-of-all-the-domain-controllers-in-my-domain.aspx">this</a>) and the <i>Site</i> they&#8217;re in.</li>
<li>For each DC/Site, select <span style="font-family: Bitstream Vera Sans Mono,Courier New,monospace;">nTDSConnection</span> objects in <i>NTDS Settings</i>. Of course this is done by means of LDAP queries over <a href="http://en.wikipedia.org/wiki/ActiveX_Data_Objects">ADO</a>, but the view we get is equivalent to what we&#8217;re seeing in <i>Active Directory Sites and Services</i>.</li>
<li>Print the DOT graph on standard output: DCs, connections and sites. DCs in the same site will be clustered together.</li>
</ul>
<p>To use it, first generate the graph&#8217;s definition:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">cscript /nologo ntdsconnections_graph.vbs &gt; AD-pre.dot</div></div>
<p>Then use Graphviz&#8217;s tools to lay out the graph and turn it into an actual image. For optimal results, I suggest something like:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ccomps -x AD-pre.dot | dot | gvpack -u | neato -Tpng -n2 &gt; AD-pre.png</div></div>
<p>Here&#8217;s what showed up, in my test case:<br />
<a href="http://www.108.bz/wp-content/uploads/2010/04/AD-pre.png"><img src="http://www.108.bz/wp-content/uploads/2010/04/AD-pre-300x160.png" alt="" title="AD-pre" width="300" height="160" class="alignnone size-medium wp-image-454" /></a></p>
<p>And here&#8217;s the same Domain, after some treatment:<br />
<a href="http://www.108.bz/wp-content/uploads/2010/04/AD-post.png"><img src="http://www.108.bz/wp-content/uploads/2010/04/AD-post-300x104.png" alt="" title="AD-post" width="300" height="104" class="alignnone size-medium wp-image-455" /></a><br />
Such graphs may be useful from a Sysadmin point of view, but they&#8217;re quite ugly, honestly. I originally thought to use Graphviz to output &#8220;some&#8221; format, read it in <a href="http://projects.gnome.org/dia/">Dia</a> or similar diagram drawing software, and then fix the aesthetics. But Dia support (if it ever worked) has been dropped from Grapviz (<a href="http://www.graphviz.org/cvs/ChangeLog">December 10, 2009</a>). Dia&#8217;s 0.97.1 tarball bears a &#8220;dot2dia.py&#8221; plugin, but I haven&#8217;t hacked it into working. Any other editable format known to Graphviz (e.g.: SVG) doesn&#8217;t support &#8220;connector&#8221; primitives meaning that arrows won&#8217;t stick to objects while you drag them around&#8230; I&#8217;ll follow up if I make some progress.</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;height:300px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">' A/D replication topology graph (Graphviz .DOT format)<br />
</span><span style="color: #008000;">' in the current Domain.<br />
</span><span style="color: #008000;">' ----------------------------<br />
</span><span style="color: #008000;">' Giuliano - http://www.108.bz<br />
</span><br />
<span style="color: #000080;">Set</span> objRootDSE = GetObject(<span style="color: #800000;">&quot;LDAP://RootDSE&quot;</span>)<br />
strConfigurationNC = objRootDSE.<span style="color: #000080;">Get</span>(<span style="color: #800000;">&quot;configurationNamingContext&quot;</span>)<br />
<br />
<span style="color: #000080;">Set</span> adoCommand = CreateObject(<span style="color: #800000;">&quot;ADODB.Command&quot;</span>)<br />
<span style="color: #000080;">Set</span> adoConnection = CreateObject(<span style="color: #800000;">&quot;ADODB.Connection&quot;</span>)<br />
adoConnection.Provider = <span style="color: #800000;">&quot;ADsDSOObject&quot;</span><br />
adoConnection.<span style="color: #000080;">Open</span> <span style="color: #800000;">&quot;Active Directory Provider&quot;</span><br />
adoCommand.ActiveConnection = adoConnection<br />
<br />
strBase = <span style="color: #800000;">&quot;&lt;LDAP://&quot;</span> &amp; strConfigurationNC &amp; <span style="color: #800000;">&quot;&gt;&quot;</span><br />
strFilter = <span style="color: #800000;">&quot;(objectClass=nTDSDSA)&quot;</span><br />
strAttributes = <span style="color: #800000;">&quot;AdsPath&quot;</span><br />
strQuery = strBase &amp; <span style="color: #800000;">&quot;;&quot;</span> &amp; strFilter &amp; <span style="color: #800000;">&quot;;&quot;</span> &amp; strAttributes &amp; <span style="color: #800000;">&quot;;subtree&quot;</span><br />
<br />
adoCommand.CommandText = strQuery<br />
adoCommand.Properties(<span style="color: #800000;">&quot;Page Size&quot;</span>) = 100<br />
adoCommand.Properties(<span style="color: #800000;">&quot;Timeout&quot;</span>) = 60<br />
adoCommand.Properties(<span style="color: #800000;">&quot;Cache Results&quot;</span>) = <span style="color: #000080;">False</span><br />
<br />
<span style="color: #000080;">Set</span> adoRecordset = adoCommand.Execute<br />
<br />
<span style="color: #000080;">Dim</span> dictDCtoSite<br />
<span style="color: #000080;">Set</span> dictDCtoSite = CreateObject(<span style="color: #800000;">&quot;Scripting.Dictionary&quot;</span>)<br />
<span style="color: #000080;">Dim</span> dictSites<br />
<span style="color: #000080;">Set</span> dictSites = CreateObject(<span style="color: #800000;">&quot;Scripting.Dictionary&quot;</span>)<br />
<span style="color: #000080;">Dim</span> arrLink()<br />
<br />
<span style="color: #000080;">Function</span> pp(s)<br />
&nbsp; &nbsp; pp = Replace(right(s,len(s)-3), <span style="color: #800000;">&quot;-&quot;</span>, <span style="color: #800000;">&quot;_&quot;</span>) <span style="color: #008000;">' trash the leading &quot;CN=&quot;<br />
</span><span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<br />
<span style="color: #000080;">Do</span> <span style="color: #000080;">Until</span> adoRecordset.EOF<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> objDC = _<br />
&nbsp; &nbsp; &nbsp; &nbsp; GetObject(GetObject(adoRecordset.Fields(<span style="color: #800000;">&quot;AdsPath&quot;</span>).Value).Parent)<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> objSite = _<br />
&nbsp; &nbsp; &nbsp; &nbsp; GetObject(GetObject(objDC.Parent).Parent)<br />
&nbsp; &nbsp; dictDCtoSite.Add objDC.name, objSite.name<br />
&nbsp; &nbsp; <span style="color: #000080;">if</span> <span style="color: #000080;">not</span> dictSites.Exists(objSite.name) <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; dictSites.Add objSite.name, 1<br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; adoRecordset.MoveNext<br />
<span style="color: #000080;">Loop</span><br />
adoRecordset.<span style="color: #000080;">Close</span><br />
<br />
<span style="color: #000080;">For</span> <span style="color: #000080;">Each</span> strDcRDN <span style="color: #000080;">in</span> dictDCtoSite.Keys <br />
&nbsp; &nbsp; strSiteRDN = dictDCtoSite.Item(strDcRDN)<br />
<br />
&nbsp; &nbsp; strNtdsSettingsPath = <span style="color: #800000;">&quot;LDAP://cn=NTDS Settings,&quot;</span> &amp; strDcRDN &amp; _<br />
&nbsp; &nbsp; <span style="color: #800000;">&quot;,cn=Servers,&quot;</span> &amp; strSiteRDN &amp; <span style="color: #800000;">&quot;,cn=Sites,&quot;</span> &amp; strConfigurationNC<br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> objNtdsSettings = GetObject(strNtdsSettingsPath)<br />
<br />
&nbsp; &nbsp; objNtdsSettings.Filter = Array(<span style="color: #800000;">&quot;nTDSConnection&quot;</span>)<br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">For</span> <span style="color: #000080;">Each</span> objConnection <span style="color: #000080;">In</span> objNtdsSettings<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">'WScript.Echo strSiteRDN &amp; &quot; : &quot; &amp; Split(objConnection.fromServer, &quot;,&quot;)(1) &amp; &quot; -&gt; &quot; &amp; strDcRDN <br />
</span>&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">ReDim</span> <span style="color: #000080;">Preserve</span> arrLink(2,k)<br />
&nbsp; &nbsp; &nbsp; &nbsp; arrLink(0,k) = strSiteRDN<br />
&nbsp; &nbsp; &nbsp; &nbsp; arrLink(1,k) = Split(objConnection.fromServer, <span style="color: #800000;">&quot;,&quot;</span>)(1)<br />
&nbsp; &nbsp; &nbsp; &nbsp; arrLink(2,k) = strDcRDN<br />
&nbsp; &nbsp; &nbsp; &nbsp; k = k + 1<br />
&nbsp; &nbsp; <span style="color: #000080;">Next</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> strNtdsSettingsPath = <span style="color: #000080;">Nothing</span><br />
<span style="color: #000080;">Next</span><br />
<br />
<span style="color: #000080;">Dim</span> arrSubgraphs()<br />
<span style="color: #000080;">Redim</span> arrSubgraphs(dictSites.Count-1)<br />
<br />
WScript.Echo <span style="color: #800000;">&quot;Digraph AD {&quot;</span><br />
WScript.Echo <span style="color: #800000;">&quot; &nbsp;fontname=helvetica;&quot;</span><br />
WScript.Echo <span style="color: #800000;">&quot; &nbsp;node [fontname=helvetica];&quot;</span><br />
<span style="color: #008000;">' Same site links<br />
</span><span style="color: #000080;">For</span> <span style="color: #000080;">Each</span> strSiteRDN <span style="color: #000080;">in</span> dictSites<br />
&nbsp; &nbsp; nosamesitelinks = <span style="color: #000080;">True</span><br />
&nbsp; &nbsp; headerwritten = <span style="color: #000080;">False</span><br />
&nbsp; &nbsp; <span style="color: #000080;">For</span> k = 0 <span style="color: #000080;">To</span> <span style="color: #000080;">Ubound</span>(arrLink, 2)<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">If</span> strSiteRDN = arrLink(0,k) <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">if</span> dictDCtoSite.Item(arrLink(1,k)) = dictDCtoSite.Item(arrLink(2,k)) <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">if</span> nosamesitelinks <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nosamesitelinks = <span style="color: #000080;">False</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WScript.Echo <span style="color: #800000;">&quot; &nbsp; &nbsp;subgraph cluster_&quot;</span> &amp; pp(strSiteRDN) &amp; <span style="color: #800000;">&quot; {&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; headerwritten = <span style="color: #000080;">True</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WScript.Echo <span style="color: #800000;">&quot; &nbsp; &nbsp; &nbsp; &nbsp;&quot;</span> &amp; pp(arrLink(1,k)) &amp; <span style="color: #800000;">&quot; -&gt; &quot;</span> &amp; pp(arrLink(2,k)) &amp; <span style="color: #800000;">&quot;;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Next</span><br />
&nbsp; &nbsp; <span style="color: #000080;">If</span> headerwritten <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; WScript.Echo <span style="color: #800000;">&quot; &nbsp; &nbsp; &nbsp; &nbsp;label= &quot;</span><span style="color: #800000;">&quot;&quot;</span> &amp; pp(strSiteRDN) &amp; <span style="color: #800000;">&quot;&quot;</span><span style="color: #800000;">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; WScript.Echo <span style="color: #800000;">&quot; &nbsp; &nbsp;}&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<span style="color: #000080;">Next</span><br />
Wscript.Echo<br />
<span style="color: #008000;">' Inter-site links<br />
</span><span style="color: #000080;">For</span> k = 0 <span style="color: #000080;">To</span> <span style="color: #000080;">Ubound</span>(arrLink, 2)<br />
&nbsp; &nbsp; <span style="color: #000080;">if</span> dictDCtoSite.Item(arrLink(1,k)) &lt;&gt; dictDCtoSite.Item(arrLink(2,k)) <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; WScript.Echo <span style="color: #800000;">&quot; &nbsp; &nbsp;&quot;</span> &amp; pp(arrLink(1,k)) &amp; <span style="color: #800000;">&quot; -&gt; &quot;</span> &amp; pp(arrLink(2,k)) &amp; <span style="color: #800000;">&quot;;&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<span style="color: #000080;">Next</span><br />
WScript.Echo <span style="color: #800000;">&quot;}&quot;</span></div></div>
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-443-1'>No powerful and convenient data types, no free and ready to use debugger, no public CPAN-like module repository, unnecessarily verbose syntax; I may go on for an hour&#8230; <span class='footnotereverse'><a href='#fnref-443-1'>&#8617;</a></span></li>
</ol>
</div>
 <img src="http://www.108.bz/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=443" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://www.108.bz/posts/it/active-directory-graphs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
