When I first read these words in February 2024, I hoped there had been a misunderstanding. The feedback suggested our setup fell short of carrier expectations, which, for a while, gave way to self-doubt. The vast majority of 20tele customers had no requirement for administrative access to their phone systems, let alone visibility of how we connect to our choice of carrier, a supplier responsible for calls and numbering. These were external routing decisions made by 20tele on their behalf, and we chose to operate as an MSP in our own way.
Let's go back
At the time, we didn't resell trunks and numbers as standalone products, and we certainly weren't handing over wholesale account credentials to end users. Instead, we provided "end-to-end maintenance" with complete control over the server hosting, configuration, and security. We deployed single PBX instances and always used IP authentication. Routing calls through any sort of SBC, whatever that meant, simply wasn't on our radar.
"How do you bill?" they asked in a follow-up call. I still think about it now, occasionally. Were they laughing at us or genuinely concerned? I didn't know. Both, probably. Deep down, I knew spending a couple of hours each month identifying caller IDs manually wasn't the best way to make sense of CDRs, but that was how we billed and didn't really care. The manual process mirrored our lean, unconventional approach. If we got much bigger, we would have to do something about it and probably throw money at the problem. I guessed an aggregating hub of some description would be the solution.
For now though, I had neither money nor time to waste.
My comfort zone
I knew FreePBX inside and out, perhaps considered an expert by most, and I was staring at user guides for FreeSWITCH and Kamailio with absolutely no clue what to do. I felt helpless and didn't want to learn something new. I was resistant to paying for per-channel licensing with Sangoma's NetBorder, which was starting to feel like the only obvious choice. It didn't seem like a fair fight, and it certainly wasn't appropriate to purchase licenses for testing purposes. Why were we being made to do this? Put simply, it felt like a backwards step.
We had spent six years deploying independent PBXs, moving away from any sort of multi-tenancy and opting for a straight-through shot to and from the carrier, without unnecessary complexity or bloated infrastructure. There were no known single points of failure, and I was proud of it. As far as I was concerned, FreePBX was the only way, with nothing in between. Yet these comments suggested it wasn't up to standard. Nonsense but fine, I thought. I felt the apparent criticism was unjustified but relished the challenge to meet their approval. Whatever so-called "best practice" meant, FreePBX would be doing it.
Disclaimer
This is not a polished, carrier-grade setup with racks of hardware and complicated load balancing. We have deliberately kept things straightforward. When it comes to scaling, we simply expand horizontally by spinning up another FreePBX pair in the cloud. There is no need for grand designs. It is proven, flexible, and anyone who knows FreePBX can manage the setup. There is no need for us to reveal everything we do to keep ourselves and our customers safe. For a concise illustration, we will default to UDP and port 5060. Security and compliance are key priorities for 20tele, and FreePBX is more than capable of handling what matters and more. We use strict IP authentication between SBCs and PBXs, tightly controlling what calls are allowed in and out, and know FreePBX back to front. Problems show up early, get solved fast, and the whole thing keeps running as intended. If we ever want to change something, we can handle it quickly. Asterisk talks to Asterisk seamlessly and nothing is lost in translation. I agree that Asterisk manages calls by sitting between both parties, unlike a pure SBC that might pass traffic straight through. This style of setup is not for every environment, and that's fine. Our setup may not suit you, but it has been solid for almost two years. Keep an open mind and enjoy the story.
The Experiment
Could I configure FreePBX to have all the hallmark characteristics of an SBC? There was nothing already done that was worth copying. In fact, wherever I looked, the general idea was shut down. "Asterisk is a B2BUA," experts said, implying that trying to make FreePBX behave like an SBC was either redundant or misguided. I wasn't surprised, but I didn't understand it enough to agree. Google searches tried to deter me further. If ChatGPT was a thing back then, it wasn't yet on my radar and couldn't warn me against technical debt.
Asterisk acts as the middleman between two call legs, managing each side separately rather than just passing traffic straight through like a simple SIP proxy. Some say this means FreePBX cannot really be an SBC in the strict sense. Yes, Asterisk gives you control over calls, but it does not have all the specialised features of dedicated SBCs built in. You will find plenty of debate about this on the FreePBX Forums, and indeed many recommend putting an SBC or SIP proxy in front of FreePBX for larger setups and carrier-grade deployments.
Despite the questions and doubts hanging over me, I decided to push ahead. I knew going down this road wouldn't be perfect, but it might still work for us. FreePBX was familiar, reliable, and within my control. The alternative felt daunting and expensive, so I chose pragmatism over perfection. Trial and error, along with considered and careful tweaks, could get us there. Ultimately, it was about delivering a manageable system that would serve our customers well. That mattered far more than ticking every box.
If the idea failed, I would at least learn something along the way. But if it worked, it would prove what I already suspected, that FreePBX could do far more than most people gave it credit for.
Undeterred, I remember thinking about the quote: "Everything is impossible until it's done."
Getting my ducks in a row
I considered how many people have seriously tried using FreePBX as an SBC in recent years, especially with PJSIP reaching maturity and fulfilling the current capabilities of modern Asterisk. I had a clear goal but no blueprint for how to get there. I didn't start with a manual or a step-by-step guide. I experimented creatively, leveraging FreePBX's default strengths to find what worked. A lot of the things I tried failed abruptly, but I will not waste your time discussing those. Instead, I'll take you through what worked and how I achieved the end result. Spoiler alert: it works. I was able to build something that mimicked SBC functionality in almost every way, while ensuring the design remains scalable, secure, and stable.
My approach to understanding Asterisk, and therefore FreePBX, is that logic and common sense almost always apply. It should work like that and therefore it generally does. If it doesn't, you are usually doing something wrong, or you are coming up against deliberate denial by design that prevents you from doing it, and that needs to be creatively circumvented.
Pairs
I decided to create two SBC pairs, one for inbound and one for outbound. In over 15 years, I hadn't seen inbound and outbound fail simultaneously at carrier level. So, keeping them separate seemed sensible to me. It meant each side could focus on its own job without crossing paths or interference. The inbound pair would only ever handle traffic coming from the carrier, and the outbound pair would only ever handle traffic leaving the PBXs.
If something went wrong and it wasn't DNS, I would know exactly where to look. The layout gave me confidence that one fault wouldn't bring everything down. There was nothing fancy about it. Just two pairs doing their own thing, each made up of a primary VM in London and a failover VM in Manchester waiting patiently in the background, always ready to take over if the other went down. From a maintenance point of view, too, it felt right. Each server could be independently updated, rebooted, or tested with very little chance of upsetting one of its siblings.
I spun up four FreePBX deployments simultaneously at Vultr with dedicated CPU, which they call "Optimized Cloud Compute". Two in London (the primaries) and two in Manchester (the failovers). Hesitant and anticipatory, fuelled by excitement, it was an emotional combination that made me unusually nervous. This was much more premium than we were used to, and relatively expensive when compared with the shared CPU we typically use. The installation was fast, and I felt a wave of confidence. Each server was allocated just 4GB RAM and 75GB disk space. You might think that's low for this requirement but, remember, this was for simple call processing and Vultr makes it extremely easy to upgrade virtual resources for better performance.
DNS
If we were to drive down this multi-tenant road in production, we would need an automated approach to resilience whenever and however it might be called upon. Manually changing A-records was an option, but it would take far too long, especially under pressure and in panic mode. I am sure many of you have been there in poor lighting at 04:00, unable to think clearly until that second cup of coffee hits.
I needed an FQDN for the trunks, with some form of automated A-record failover. The options available were surprisingly limited. Who knew something so obvious could be relatively niche?
ClouDNS were the standout provider for A-record failover, monitoring, and DDoS mitigation. This meant a single A-record could instantly switch IP address from the primary SBC to the failover SBC, in either direction, and between the primary PBXs to the failover PBXs, and revert automatically. After considerable testing, they exceeded my expectations for both price and functionality. They seem like nice people too; responsive, approachable, and always quick to answer every technical and commercial query. ClouDNS continue to be everything a company like this should be.
DNS propagation needed to be fast. No matter how quickly ClouDNS might react, it ultimately comes down to how the systems themselves respect the 1-minute TTL.
For DNS, FreePBX defaults to 127.0.0.1 for simplicity in standalone systems, where caching helps with speed and reliability. But in our case, we needed an immediate response to heartbeat monitoring at ClouDNS, and local caching became a serious liability. The PBX may continue using an outdated record long after ClouDNS has switched the A-record to a new IP, defeating the point of automated IP address replacement. External resolvers like Cloudflare or Google can be trusted to keep everything accurate to the minute, which is exactly what we needed in this design.
I replaced the default 127.0.0.1 entry with external resolvers. Using the loopback address would have forced local lookups, relying on cached data instead of checking ClouDNS directly. That's fine, in static setups, but not when call routing depended on live responses. ClouDNS hosts our authoritative records and manages the IP address replacement, but the SBCs and PBXs still need to query through a resolver to reach it. I chose Cloudflare's 1.1.1.1 and 1.0.0.1 for speed and reliability, with Google's 8.8.8.8 and 8.8.4.4 as a third and fourth option in case of response issues.
Trunks
I didn't yet know that the trunks were central to everything. PJSIP is modern and flexible, but turning FreePBX into an SBC-like middleman meant reworking how we consistently set these up.
I created four trunks, named with odd numbers for the failover SBCs and even numbers for primary SBCs. 1 and 2 would be inbound, 3 and 4 would be outbound.
I was able to use the FQDNs created at ClouDNS, each PBX and SBC with its own subdomain. If you have any doubts about DNS propagation, point straight at the IP addresses during testing.
Both Allow Anonymous Inbound SIP Calls and Allow SIP Guests are set to No. The SBCs and PBXs only ever talk to trusted IPs, and there's no reason to accept unknown traffic. Turning either of these on would invite unwanted SIP messages and random call attempts from the public internet. Leaving them set to No keeps everything locked down. The SBCs only accept requests from recognised sources and reject everything else by default, without mentioning robust firewall configuration.
IP authentication proved simple to set up. Authentication > None and Registration > None at both ends. Timing was crucial here though to avoid authentication failures, as Asterisk needed to be reloaded by clicking Apply Config simultaneously on the SBC and PBX.
Inbound SBCs
With DNS failover working nicely, the setup was beginning to take shape. The SBCs were in two pairs, the A-record was reliably switching, and the notifications were instant via email and SMS. My concerns about single points of failure were easing. PJSIP extensions provisioned with the same UDP trunks were able to reroute just as effortlessly.
Next came configuration of the trunks to handle SIP traffic in an SBC-like way. This meant setting up trunks in a hub-and-spoke design, securing them with an internal-use mindset, and ensuring calls flowed correctly and completely.
The inbound SBC pair, servers 1 and 2, are deliberately plain. Think of them as two doormen. Their only job is to accept calls from the carrier and hand them to the right PBX. Nothing more. No manipulation, no IVRs, no queues. Very little decision making and a clean handoff.
Numbers hosted by the carrier always point to the primary SBC. If the IP address is unreachable, they have a sequential list of others to try until it comes back up. We let the carrier natively handle inbound failover, achieved by pinging what we estimate to be every 15 seconds. Rather than using ClouDNS again, this alleviated worries that a DNS-related outage there might take everything out, pointing directly at the IP addresses instead. Again, IP authentication at both ends was essential here. This meant only calls from our carrier's IPs were permitted.
With the trunks set, the next step was to route incoming calls. FreePBX's Inbound Routes module was ideal for this. We created routes to catch calls from the carrier and direct them to the correct PBX. Each route used a DID pattern to match incoming numbers, ensuring calls always landed where they should. For example, an inbound call to a customer's mainline number would hit the primary SBC first, rapidly checked against firewall rules, and then handed to that customer's FreePBX instance.
Each inbound route forwarded to a custom destination for added control, giving me a place in the dialplan to adjust behaviour before passing the call onwards. The flow was straightforward:
Carrier trunk → SBC Inbound Routes → Trunk to PBX → PBX Inbound Routes
This pass-through kept things simple and efficient, without unnecessary steps.
This separation was deliberate. The SBC moved calls securely and predictably. The PBX handled the customer experience perfectly and with very little effort. The doormen let calls into the building and showed them down the hallway. What happened next was up to the PBX itself.
Outbound SBCs
Outbound was trickier. I didn't know what I was getting into, but it quickly became obvious once calls started flowing the wrong way. This blog post might save you hours or even days. Something about outbound logic in FreePBX just isn't built for this kind of role. The inbound side was simple enough, but getting calls to leave cleanly and predictably was another story.
As I said, my approach to understanding Asterisk and therefore FreePBX, is that logic and common sense almost always apply.
Every PBX needed a way to identify itself, and that's when the idea of prefixes came to mind. What if each PBX had its own tag, something unique that travelled with every call? It wasn't part of any guide or best practice I could find, but it felt right. I started testing it, tagging each call with a numerical identifier to see what would happen.
Bingo. That one change opened the door. Suddenly the SBCs could tell where calls came from, and I could start shaping the outbound flow properly. This was an exciting breakthrough that was working, sort of. It was then that I noticed the paradox of every outbound call landing on an inbound route. This was confusing at first but understandable once I grasped how Asterisk handles incoming requests. FreePBX itself treats everything it receives as inbound traffic, even when the call is on its way out from a connecting PBX. It looked wrong at first, but that small contradiction was exactly what made the whole setup possible. It wasn't perfect yet, but this was the moment the penny dropped.
Custom Destinations
I quickly discovered that FreePBX does not allow you to send a call directly from an inbound route to an outbound route. Urgh. This is what I meant earlier about deliberate denial by design. Outbound routes are not destinations, and they work by matching dialled patterns when a call is placed internally. Without intervention, inbound calls arriving at the SBC would simply have nowhere to go.
That limitation forced a rethink, and the answer came in the form of custom destinations. FreePBX's Custom Destinations module allows you to build controlled dialplan logic without editing config files. By sending calls from Inbound Routes on the SBC to a custom destination, I could insert the prefixes as an identifiable tag to make Outbound Routes recognise and process the traffic correctly.
That extra hop was the key that unlocked everything. Without it, calls would fail. With it, the outbound logic flowed effortlessly and the whole process clicked into place.
PBX Outbound Routes → PBX trunk → SBC Inbound Routes → Custom Destinations → SBC Outbound Routes → Carrier trunk.
For Outbound Routes, the structure would become lengthy but organised. Each billing account had its own set of routes: Domestic, UK-Other, International, Premium, Emergency. For 20tele, the route names were clear, billable, and tied to the PBX pair they belonged to. Within the configuration, trunks were sequenced to ensure resilience with our preferred carrier "first in route" and another as a fallback, so calls would always have a path out.
Dial patterns did the final clean-up. Whether a user dialled with 0, 44, or +44, the system normalised the number into E.164 before sending it out. The prefixes remained in place and every call stayed traceable to both the account and the PBX.
We also applied stricter rules where the risk was greater. Premium and International routes only allowed the specific Caller IDs we defined. This stopped spoofing on expensive traffic and limited exposure if a PBX was ever compromised.
Domestic routes had to stay open. Enforcing Caller IDs there would break call forwarding whenever the original number was unknown to us. It is also important to note that call forwarding to these premium rates would be blocked. This would be a highly unusual request in any case and easily opened up if the customer demanded it. That balance was deliberate: strict where it mattered, flexible where it was necessary.
P-Asserted-Identity (PAI) must be sent on the outbound trunk from your SBC, or whatever the carrier expects. You should have disabled this between the PBX and the SBC in both directions.
Billing and CDRs
A bonus of the prefix approach was that it showed up in the CDRs. Every call carried the account number and a PBX identifier. That meant billing was effectively built in.
Try making sense of CDRs in FreePBX and you'll need several hours to carry out some fairly basic analysis. Ok, that may be a slight exaggeration, but the complexity of call flows means an IVR shows the calls as being ANSWERED, while NO ANSWER shows up for everything else after that, except the extension that did answer, which turned out to be call forwarding and now shows as an outbound call. Got it? Me neither. Sprinkle in some FAILEDs and BUSYs, and you will have no idea what actually happened without trawling through an entire spreadsheet for a single call. This assumes you were able to find it after inevitably choosing the wrong search filter.
And breathe. Put simply, the SBCs fixed all that. I could see one call in and one call out. I was filtering for fun by PBX and by customer, or both, and I was no longer presented with noisy data. Just billable calls, beautifully arranged in chronological order.
A record like 123*456*447984378437 was easy to read. It told me the call belonged to billing account 123, came from PBX 456, and dialled UK mobile +447984378437. A customer could have multiple PBXs and one billing account, and vice versa. Like a PIN, 123*456 had to be sent as an exact match and from an authorised IP address. That single string held the key our CDRs desperately needed and billing became centralised. No reconciliation or reformatting, no third-party tools, no painstaking detective work.
As the outbound routes were now tied to accounts, I could also decide what traffic types each account could access: Domestic only for some, Premium enabled for others, and with alerts for more expensive call types. The same rules applied consistently across all PBXs within the account. This also meant we could control what call types were allowed no matter what was sent to us.
The prefixes were now doing so much more than routing. They created billing accuracy, fraud protection, and visibility end to end. The CDRs proved our workings. Every call was accounted for.
Concurrency Count
Even with everything running smoothly, I still couldn't see one crucial data point: how many calls were happening at once? FreePBX shows live activity but no history, and I wanted proof of what was really going on. So, I wrote Concurrency Count.
It reads the CDRs, works out overlapping calls, and shows true concurrency to the second for trunks, extensions, or full system totals. No setup, no dependencies, just Bash and MySQL/MariaDB. It runs locally, finishes in seconds, and leaves nothing behind.
It quickly showed that most systems use far fewer channels than they pay for. Providers base their models on oversubscription, assuming you will never hit your limit. Concurrency Count ends that guesswork and shows exactly what you used, when, and where.
I didn't build it to sell anything. I built it because I wanted the truth for our internal systems. Once I got it working, I knew others would want it too. It is free, open source, and available on GitHub for anyone running FreePBX or PBXact.
The outage
In November 2025, Vultr had an outage. It was the worst downtime 20tele has ever dealt with, in both time and exposure. Total primary data centre failure in London, every server in that data centre lost, no recovery possible within the same location. This was the exact scenario the paired SBC build was designed for, right? Right?
Wrong. It didn't cope with it well at all, and the SLA credits awarded were a costly end to 2025.
On a positive note, the heroes in this story did their job: the failover SBCs in Manchester stayed up and were always ready to process calls. DNS health checks triggered correctly and ClouDNS replaced the A-records within seconds. Wherever the call path existed, calls were flowing through Manchester as designed.
For about 15 minutes, I thought we had proven the whole concept. Like that cinematic pause when you hoped the Titanic was turning clear of the iceberg. That tense silence before everything fell apart. If you have ever experienced something similar on this scale, you know exactly how we felt and what was happening to us.
DNS propagation varied wildly across different networks. Some resolvers picked up the new records immediately, others cached the old IP address for far too long despite the TTL settings. VPN certificates were mismatched between the primary PBXs and the failover PBXs, and I lost control of most Sangoma P-Series and S-Series phones. Anyone familiar with Endpoint Manager knows how frustrating that can be; once gone those phones rarely come back without human, on-site intervention.
Some number ranges from our days as a reseller hit supplier-side constraints, which politely means they were far too slow. Our phones didn't stop ringing and explaining a live situation to customers only slowed progress. Seconds turned into minutes and what felt like hours. Sam and I had never encountered pressure like it. 20tele never actually needed to reroute numbers en masse under genuine failure conditions.
Some customers were operating normally within minutes. Others took up to 90 minutes, only returning when London came back online. The incident report was made public and candidly documents exactly what failed. There was no one to blame but ourselves.
What frustrated me most was that the part some might question had actually worked. I started writing this story three months before the outage happened. The unconventional bit, the FreePBX-as-an-SBC architecture, performed exactly as intended. The call routing logic held. The prefixes stayed intact. The CDRs showed us who was making and receiving calls without issues. Where a path existed, calls continued successfully. The SBC layer was never the problem.
Everything I had assumed to be bulletproof turned out to need serious work.
That 90 minutes taught me more about resilience than almost two years of smooth running ever could. Theoretical knowledge means nothing in production. Practical experience showed how third-party DNS actually behaves in real-time when urgency is required. Even our emails hit unforeseen rate limiting and broke. This is the difference between a system that looks resilient on paper and one that can prove it under genuine pressure.
We trawled through mountains of log files and hardened every weakness we found. Improved DNS handling, rebuilt certificate management, validated rerouting capabilities with every supplier rather than assuming they would work. One password mismatch from a re-registering extension got a customer site of 30 users banned on their failover PBX, so Fail2Ban works even when that would be inconvenient. The way 20tele approach resilience today is measurably stronger because we failed in identifiable ways, rather than collapsing into irrecoverable unidentifiable chaos.
The architecture I had defended for two years held up to scrutiny. The infrastructure I had taken for granted did not.
Reflections
Before I started this project, I was told our setup was not best practice. The subtext was clear: unless you follow the carrier's path and pay for their way of doing things, you are not a serious provider. That doubt lingered, but I kept building anyway. The deeper I went, the more I realised that their understanding of "best practice" was written for carriers with endless resources, not for MSPs who need to stay lean and flexible.
20tele is not a carrier. We are an MSP. Our value is in maintaining hosted phone systems that are scalable, secure, and stable. If we do that competently for PBXs, we can do the same for SBCs. Customers do not want to know about trunks, SBCs, or dial plans. They want their phones to work every time. That was the only standard worth chasing.
I should point out, there is a lot we didn't do. There are no extensions and limited use of modules, although we did upgrade all four SBCs from FreePBX to PBXact, which gave us unrestricted access to 12 commercial modules. I thought some may enhance SBC functionality and provide extra safety measures, but didn't end up using any of them.
I was drawn to Outbound Call Limit, alas only available as part of the PBXact Call Centre add-on. This commercial module prevents too many calls being made over a specified period of time: hours, days, or months. You can limit the number of calls to a particular type, and an error message is played to the user when the limit is reached. It is especially useful for outbound campaigns if you are trying to control callbacks, manage workload, or prevent burnout. For SBC purposes, it would act as an effective fraud control tool by limiting volumes to costly destinations, such as international calls.
Perhaps Sangoma will consider including Outbound Call Limit as standard within PBXact, or offering it as a standalone purchase. I would certainly use it with all our SBCs. PBXact makes it a relatively costly choice when there is no requirement for the rest of the bundle.
The Duck Test
On paper, FreePBX is not an SBC. It is a B2BUA. But the Duck Test applies. If it routes like an SBC, secures like an SBC, and bills like an SBC, then for us it is an SBC. Labels are less important than outcomes.
This is not carrier grade with racks of hardware and multi-million-pound infrastructure. It is service grade, designed for MSPs, lean and cloud based, tested every day by real customers making real calls. It is not theory, it is lived practice.
We didn't duck out of the challenge, nor did we buy our way to an answer. We stayed with it, broke it, fixed it, and proved it. The result is perhaps not textbook-worthy to everyone, but it is ours, and it works.
The only thing I want people to take away, is that best practice is not a rule carved in stone. It is a moving target, shaped by what actually works by those who deliver it, especially in production. If you can rely on something secure and resilient, then you are already there.
Was this a makeshift attempt to appease a carrier, who hadn't noticed our setup until I brought it up? Probably. Are we doing it properly? Definitely.
Ducks involved or not, we walked the walk. And for 20tele's customers, that is all that matters.
I am available for support and consultancy. Find me on LinkedIn and send a message.
Final thoughts
This blog post took me five months to finish. Not because I didn't know what to say, but because every time I opened it, I changed my mind about what it should be. It started as a technical explanation and slowly turned into something more personal. I thought it was almost done in November, but then the outage hit, testing it all for real.
Each time I tried to write, I got stuck somewhere between frustration and pride. This wasn't theory. It was lived experience, powered by coffee, constant distractions, and the occasional moment of staring at the screen questioning what on earth I had started. I wanted it to read honestly, not like marketing or documentation. That takes time.
We also launched VP-En for our UK customers recently and I wondered if that would make it into the final edit. It turns out, the content was already revealing enough, without then giving away all our current security practices, intentions, and roadmap on top. Ever evolving as security efforts should be, anything said would go rapidly out of date.
I thought about it every day. I kept putting it away and coming back, trying to balance detail with clarity, fact with feeling, and the urge to delete the whole thing and start again. Maybe that's the point. I knew I would be respectfully challenged, and I wanted my workings to be proof beyond any argument.
There's a certain irony to all this. The same people who insist FreePBX cannot be an SBC are the reason this story exists. That challenge is what pushed the whole experiment forward. It is easy to quote best practice when someone else wrote the rulebook, but it is more rewarding to see where those rules might actually bend.
I didn't set out to prove anyone wrong, only to prove that it could be done, and done well. I took what we already had and made it do the job, even if it meant some unconventional solutions along the way.
Building imitation SBCs was never about shortcuts, and neither was writing about it.
Now finished, it feels right. Not polished or perfect, but more than good enough.
Thanks for indulging me.
Kieran
The Duck Test