Version 1.38.0

Released: 2011-03-19

Awstats cgi support for subdomains new

Added interface for awstats cgi in DA for subdomains, as well as fixed an in the when subdomains are being processed. (wrong data path in

If you've got an incorrect, you can delete yours, and the will re-add the correct one for you.

Allow domain instead of ip with dns clustering new

You can now add a domain name into the "IP" field when adding a new remote server for the multi server setup page with dns cluster.

This will allow the value to change based on the lookup, for example, if your remote box dies and you build a new one at a different IP.

Note, this will reduce performance slightly, since a dns lookup is required each time a zone is to be transferred, but caching is likely to be used so it shouldn't hurt too badly.

Since this is changing dns settings, it would still be "safer" to use IPs, so you know exactly where it's going.

Ftp logging to skip local IPs new

If ftp traffic comes from an IP 192.168.x.x or 10.x.x.x, or then proftpd and pureftpd will skip logging their bandwidth.

Logging is also skipped if the client address is in the /usr/local/directadmin/data/admin/ip.list, since it's still local if it's from a external IP which is on the box.


Note, for this to work, you must edit your /etc/proftpd.conf and change:

LogFormat               userlog "%u %b %m"

to be:

LogFormat               userlog "%u %b %m %a"

new installs will get this by default.

pure-ftpd does not require any changes for this feature to work. called on backup failure new

Similar to the and, this will be called if there are any issues during the creation of the User Backup.

This also includes errors that may arise for the Reseller/Admin Level portions of the User backup.

Ftp uploading is not part of the check as this is done outside of the backup function.

You'd create:


the environmental variables are:

username: name of the user being backed up (which failed)

reseller: name of the account that created the User

owner: owner of the directory/files.. mainly for write-access purposes. (owner of the backup path). I if using ftp, this value will be "diradmin"

dest_path: where the backup is going. If the value is blank (""), then it's going to /home/username/backups

error_result: the actual error message as to why this is being triggered. and new

Custom scripts for when a User modifies a domain (changes ssl, bandwidth, settings, etc..)

This is not for the change of a domain name, that's and

The variables passed will be all of the variables from:


but overwritten with the new settings specified by the user in the post.

Also, the username and domain variables will be included (somewhat important)

The pre will be called after all filtering of variables, but before the write of the

The post will be call after the write, (which is essentially all that happens with the domain modification)

Like other sh scripts, you can exit with a non-zero value, and DA will abort, and display your echo'ed text.

This is mainly for the, as the is too late to abort anything (but your text will still be shown) new


custom script to be called after the user.conf is written (for user creation)

The is called before these config files are written, thus if you need to add custom values to them, you're out of luck.

The scripts will now give you the ability to do this.

The values passed to the will be the same as, eg:

full contents of data/users/user/user.conf, plus "passwd".

This script was added into the "write()" of the user classe, after the actual write of the conf files, but is only triggered if the creation was just done.

This way, we don't need to worry about adding code everywhere in DA to call these scripts, since a write always follows the creation.

Note, this feature request was initially made with the in mind (for

However, after looking at the code, it was found that the write for the domain confs are done quite early on in the creation, so the is in fact called at the correct time, thus there is no need for the

It was also found that there was a follow-up write of the, which is why the script wasn't able to make any changes.

The 2nd write was removed since it's not required.

API to get TTL of a zone new

Return the TTL value of a zone.


Will return the standard output from the urlencoded=yes listed here:

CMD_API_DNS_ADMIN & CMD_API_DNS_CONTROL return url encoded zone

plus will add a line at the bottom for the TTL:


It will be 14400 unless there is an override set in the data/users/domains/

The zone itself isn't parsed.

Use named-checkzone to better filter dns records new

Better filtering on values for CNAME and TXT records.

Use named-checkzone /var/named/ before copying the zone to

You can shut off this check by adding:


to your directadmin.conf, and restarting DA.

This feature will be enabled by default.

It's possible that you may already have zones with invalid data, but do not cause named to crash.

If this is the case, this check will block you from adding new records until the bad ones are removed/fixed.

It assumes you have:


If you don't, you'll get errors in your error.log, but the zone will still be saved.

DA will listen on all IP families: IPv4 and IPv6 (Important: FreeBSD) new


FreeBSD 4 and older are not affected.

FreeBSD 5 and above are affected

By default, the ipv6_ipv4mapping option is not enabled on these FreeBSD versions.

What this means is that any service which is using IPv6 to handle both v4 and v6 will only be using v6.

Connections to v4 will fail (except smarter applications like apache which have other tricks to bind to each family separately).

The FreeBSD team do this because when IPv6 handles both 4 and 6, the service cannot figure out which protocol is being used.

Their claim is that if you intend to allow one, but not the other, to filter packets, then it could be a security issue.

Since we don't care about what protocol is being used (we want to allow both equally, and a specific protocol is not required to login) we're going to tell the system to turn on the IPv4 mapping to IPv6 IPs (like all other OS's already do by default)

The solution, which will be automatically run by the DirectAdmin update on FreeBSD, will run the command:

/sbin/sysctl net.inet6.ip6.v6only=0

and set this in the /etc/rc.conf:


When working correctly, the sockstat command will show this:

freebsd7-64# sockstat -l | grep direct | head -n1
nobody   directadmi 50362 0  tcp46  *:2222                *:*

if not, it will show this:

freebsd7-64# sockstat -l | grep direct | head -n1
nobody   directadmi 50362 0  tcp6  *:2222                *:*

we want to see tcp46 in the output, else it's not enabled.

Note, DirectAdmin must be restarted after this option is set.

Note that the will do all of this for you.. the Admin shouldn't need to take any action to get this to happen.

However, I feel the above information is very important and Admins need to know what's being done, why, and how.

** Report on a system that didn't have IPv6 compiled in, required directadmin.conf option:


to be added to prevent "Socket error - try again in 30 seconds".


*** EDIT for one reported case on Debian ***

This is not part of the update, but for this reported case, it was required to make DA work on IPv4:



net.ipv6.bindv6only = 1


net.ipv6.bindv6only = 0

and type:

echo 0 > /proc/sys/net/ipv6/bindv6only

The sockets class has been rewritten to support IPv6 IPs.

If you system doesn't support IPv6 IPs, DA will realize the socket call failed and will redo the call with the AF_INET family instead of AF_INET6.

To check if your DA binary is compiled with IPv6 support, type:

[root@server]# cd /usr/local/directadmin
[root@server]# ./directadmin o
Compiled on 'Redhat CentOS 4.0'
Compile time: Feb 16 2011 at 15:49:34
Compiled with IPv6
[root@server]# netstat -lnp | grep 2222
tcp        0      0 :::2222                     :::*                        LISTEN      10905/directadmin

and look for the "Compiled with IPv6" text.

No text, means it's not setup.

You can also confirm with the netstat call.

If it's bound to :::2222, then it's IPv6.

If it's bound to then it's only IPv4.

Binding to IPv6 allows connections on both IPv4 and IPv6.

The bind_address should still work fine, however if you're going to use an IPv6 IP to bind to, be sure to use the full format, and not the shorthand format.

Note: You do not need to have ipv6=1 for DA to bind to IPv4 and IPv6. DA will do this regardless of the ipv6 setting.




List current permissions for given User:

method: GET

Sample output:


To set permissions for a given User:

method: POST

commands.allow and commands.deny for per-user control new

Allow/Deny Users specific commands based on these files, if they exist.

They won't exist by default.


They work in a similar manner to the /etc/hosts.allow|deny files.

  • commands.allow overrides commands.deny. If an item is in both, the command will be allowed.

  • if commands.allow exists, but is empty, that User will not be able to do anything

  • adding commands to commands.allow that do not exist in the given accounts access level won't work (eg: you cannot run Admin level commands as a User)

Special keywords will be used to allow full or zero permission on an entire access level (both the allow and deny files can use them):


which would be mainly used for cases where you want the full access level of one level, but want to refer to other areas for limitations.

Example, if you want to create a Super Reseller, where that Reseller can create other Resellers, you would create an Admin account, and add:


which essentially is a Reseller, but who can create other Resellers.

The ALL_USER, ALL_RESELLER, and ALL_ADMIN values are handy to use because they'll be dynamic between versions, in case there are new commands for that level.

You will need to be careful if you're doing this example since many non-Admin commands are changed if the account is of type "Admin".

For example, CMD_SKINS is a Reseller command, but when run as Admin, it has access to the global skins folder.

CMD_SSL, when pasting a cert/key on a shared IP will be accessing the shared server certificate for the whole server.


If you allow CMD_LOGIN to an Admin or Reseller, then they will be able to call CMD_LOGIN for the "Login As" feature for accounts under their control.

As such, they'd be able to execute any commands that the logged-in User can do, regardless of their own commands.allow/deny. (They'd still be limited to that logged-in accounts command.allow/deny files, should they exist)

Added c option to top in load checker option new

The "top" output in the DirectAdmin load checker option will now have the c option for more details about the processes.

Added 'top' output to load checker

FreeBSD doesn't support this option, thus won't be used. (there are options on newer versions of top on FreeBSD, but not older ones, so no FreeBSD versions will get this change)

The top command will now be (Linux/Debian):

/usr/bin/top -c -b -n 1 | /usr/bin/head -n 30

Check email limit every minute, instead of just with the tally (ACTION REQUIRED) new

Related to Number of email deliveries in all stats

Check files of size /etc/virtual/limit (or /etc/virtual/limit_user if it exists) in the folder /etc/virtual/usage/user (not the bytes files) to see if they've hit the limit, then notify the Admin with the existing code.

New task.queue type file:


used for mail only tasks.

Similar to id=1121, this feature is affected by the options:



where an email is only sent if this is set:


and if that is set, Admins will be notified.

The option:


will also notify the User that he's hit the limit.

The User notification will not happen if notify_on_mass_emailing is not enabled.

There is a new template for this message:


It will report on the top sender, top "auth" username, top sending IP, and top path used.

Note, the path can be useful, but can also be misleading.

This is because any email sent over smtp will use exim's current working path, which could be /root, /var/spool/exim, etc... it's where ever the process's "current working path" is.

However, the path can also be very helpful in the case that you've got a rogue php/perl script sending emails from a client's account. In that case, the path would be the path the script is in, which would help more quickly identify the problem.

Added "Edit Welcome Message" link to main Reseller page. (reseller/content_main.html)

Used |LF_CREATE| at the top, and added javascript for the popup.

No language pack changes/additions are needed because of the |LF_CREATE| addition to the top.

Add /etc/virtual/limit into Admin Settings (SKINS) new

The /etc/virtual/limit file is used to limit the number of emails a DirectAdmin User can send per day.

0 is unlimited.


Add /etc/virtual/limit into Admin Settings.

This is just the global setting, and doesn't apply to overrides of /etc/virtual/limit_user, which you can do manually, in combination with the new



added an email section.

Option to specify length of the gernated random passwords (SKINS) new

Admin Settings option to set how long random passwords will be.

Applies to all random password areas. (DA account creation, email, mysql, ftp, lost password reset, resend welcome message)

directadmin.conf option:


where 8 is the internal default.

As of DA 1.45.3, the actual length is a random length, between

random_password_length and random_password_length_max

Random passwords now have a random length

If you want a different length, then add the option to the directadmin.conf with the number you want.

Values should be somewhere between 4 and 20. You can go as high as you want, but you might run into field size limits in some skins (not our skins though).

Your clients may also hate you if you expect them to memorize a 30 random character password.

Also, if you are using the difficult password enforcement option, using a lower number for the password length may cause the random password generator to fail, as it will only try 20 times to meet all criteria (Upper & lower case, number, etc). With only 4 characters, the likelihood of 20 tries not being enough is high.

The difficult_password.php script will also check this value, and lower the $min_length automatically if the random_password_length is less than 6.



var length = 8;

changed to:


This token is available as a global token.

Important Security Changes new



are now going to be enabled by default for new installs.

These values are set in the data/templates/directadmin.conf.

Existing installs will not be affected. This only applies to new installs using 1.37.1 at install time.


secure_access_group option for higher user security

Option to prevent creating subdomain of a different user.

Also, the script:


will now run:

chown webapps:apache /var/www
chmod 550 /var/www

chgrp apache /usr/bin/perl
chmod 705 /usr/bin/perl

to increase security.

The scripts/ is also only called at install time, so feel free to make these changes for existing install if you wish.

For existing systems that want all of the above to be enabled, run this:

cd /usr/local/directadmin
echo "secure_access_group=access" >> conf/directadmin.conf
echo "check_subdomain_owner=1" >> conf/directadmin.conf
/etc/init.d/directadmin restart
echo "action=rewrite&value=secure_access_group" >> data/task.queue
chown webapps:apache /var/www && chmod 550 /var/www
chgrp apache /usr/bin/perl && chmod 705 /usr/bin/perl

Add /bin/nice before tar for all calls to tar, zip, unzip. new

We've added:

/bin/nice -n $backup_nice

(FreeBSD and Debian will use /usr/bin/nice)

before all tar, zip, and unzip commands.

This includes, backup, restores, skins, and Filemanager compression/extraction.

This assumes you have "nice" in the above location for your OS.

If you don't, you will need to add it, as tar, zip/unzip will throw errors if it's missing.

No action is required. This is enabled by default for everyone.

Store original package name when custom config is used new

When you make a custom non-package change to a User, their package will become "custom".

This change will add a new value to the user.conf called:


which saves the previous package name for when the User is custom.

If package=custom and original_package exists, this value will show up when you view the User on CMD_SHOW_USER?user=user.

The same is also done for the reseller.conf and CMD_SHOW_RESELLER?user=user.

Add RBL blocking into Admin Settings (SKINS) new

The RBL (real-time block list) system is used to block bad sending IPs (usually spammers) based on a custom external dns network.

The default is set to no. Some consider the RBL system (within exim) to be too aggressive in it's judgement of emails.

It's often safer to rely on the native RBL blocking in SpamAssasin, and don't enable it with this option.


Note: This option will show enabled if /etc/virtual/use_rbl_domains is a a link, and disabled if it's a file.

If you are using the use_rbl_domains as a file and are manually updating it, leave the option disabled.

If you enable it, the file will be deleted and it will be replaced by a link to "domains".



Backup option to Admin backups (SKINS) new

Give the Admins the choice as to what data they want to have in their backups, similar to the User Level backup.

The Reseller Level will get these options for a future release of DA, if everything goes well with this change.

The backup files created will always have a core set of data (user.conf files, dns db files, etc..) but the options now give the Admin the option to skip parts of the backup (domains, databases, subdomain, email accounts, etc)

The backup tar.gz files will now have a new file in the "backup" directory called "backup_options.list"

During a restore, this file will be extracted first from the tar.gz, prior to the rest of the files.

It will contain the list of backup options used for the backup.

If the file doesn't exist, it's assume all options are to be restored.



LANG_STEP_5=Step 5
LANG_OPT_DOMAINS_DIR=Domains Directory
LANG_OPT_SUB_LISTS=Subdomain Lists


90=All Data
91=Selected Data
92=No User Data




Added this near the top:




to the td just before "Step 1" of the backup.

A large new tr is added after the first tr (step 1,2,3), before the 2nd (step 4)

Changed Step 4 to be Step 5 next to the Submit button.

Restore portion has a "partial data" checkbox., run just before backup tar.gz compression. new

Custom script:


will be called, if it exists, just before the creation of the tar.gz file.

It's called just after the assembly of the "backup" folder.

This script will be useful if you wish to copy files into the backup folder to include custom files in the User backups.

It provides all the same variables as

php path checks in show_domain.html required change (SKINS) new

Due to the changes with:

Important Security Changes

The scripts run within the skins no longer have the ability to read /var/www.

Due to this change, we've made DA check for the paths and add tokens instead:


which will be set to "yes" if their respective path exists in /var/www/html, and no if not.

This will actually speed up the page load since the php binary does not need to be read in 4 times.


power_user/user/email/email.html (not shown, but similar)

default/user/email/email.html (not shown, but similar)

enhanced/user/show_domain.html (see below)

|*if SHOW_LINKS="no"|

<a href="http://|HOSTNAME|/squirrelmail" target="_blank">|LANG_WEBMAIL_SM|</a><br>

|*if HAVE_WEBMAIL="yes"|
<a href="http://|HOSTNAME|/webmail" target="_blank">|LANG_WEBMAIL_UEBI|</a><br>

|*if HAVE_ROUNDCUBE="yes"|
<a href="http://|HOSTNAME|/roundcube" target="_blank">|LANG_WEBMAIL_ROUNDCUBE|</a><br>

|*if HAVE_ATMAIL="yes"|
<a href="http://|HOSTNAME|/atmail" target="_blank">|LANG_WEBMAIL_ATMAIL|</a><br>

<a href="/CMD_DNS_MX?domain=|domain|">|LANG_MX_RECORDS|</a><br>

Options to skip suspended accounts from backups (SKINS) new


Update other skins.

Options to skip suspended accounts from backups:

Add checkbox to bottom of step 1.

Note that this option is a game-time decision option.

The status of the account is checked the moment before it's being backed up.

You won't get a warning when creating the backup in the interface. You'll only get a summary of what happened in the post-backup message.

Skipping a suspended User does not throw any errors, so all scripts, or APIs being used.. no errors will be returned.

The won't be run, since the abort happens before that.

If you use the "Selected Users", only select 1 User, and that account is suspended, if you use this option, the account will be skipped.

If there are any cases were you may still need a backup and won't be sure if the account will be suspended, simply don't use this option.







<tr><td class=listtitle><input type=checkbox name="skip_suspended" value="yes" |SKIP_SUSPENDED_CHECKED|></td>
<td class=listtitle>
- Skip Suspended

to the bottom of the step 1 (who) table.

Remove the |SKIP_SUSPENDED_CHECKED| on the main backup pages.. that token only applies to the *_modify.html pages.

Added compile date to licenses page (SKINS) new

Added Compile Date to:

Admin Level -> Licenses/Updates




<tr><td class=list>Compile Date</td><td class=list>|compile_time|</td></tr>

Fixed addip script for IPv6 on FreeBSD new

Added the missing IPv6 code into the ipv6 script on FreeBSD.

Also moved the adding of IPv6 IPs to after the ethernet dev value is passed (all OS's) so that your actual device is used, if it's something other than eth0.

Basic DKIM back-end for outbound emails new

For current installs, use this more modern guide here:

Older, original guide:

Basic implementation of DKIM. This does not set your exim.conf for you (to do that, see below).

This only set's up the keys and adds them to the dns (which is the hard part anyway)

Only try this feature if you are comfortable with system customizations.

This requires exim 4.70 or newer.

To enable it, add this to the directadmin.conf and restart DA:


The internal default is 0.

This flag will trigger the calling of:


The script has ways of calling it:

  1. If you're wanting to add dkim to just one domain, use it like this:

which will trigger a task.queue call to add the newly created keys into dns.

  1. DA will call the script for newly created domains like this:
/ nodns

which skips the task.queue entry, as DA will add the dns right after the call to the script internall (no need to wait a minute for it to be added)

This 2nd option won't be used much.

  1. If you want to trigger the adding of dkim to all of your existing domains, use this:

echo "action=rewrite&value=dkim" >> /usr/local/directadmin/data/task.queue

This option hasn't been tested much (works find for 1.. so should work fine for all.. in theory)


Edit your /etc/exim.conf. Find this code:

  driver = smtp

change it to be:

  driver = smtp
  dkim_domain = $sender_address_domain
  dkim_selector = x
  dkim_private_key = ${if exists{/etc/virtual/$sender_address_domain/dkim.private.key}{/etc/virtual/$sender_address_domain/dkim.private.key}{0}}
  dkim_canon = relaxed
  dkim_strict = 0

and restart exim.

That should start adding the DKIM headers to your outbound emails.

Note, emails generated on the hostname (like apache/php scripts) will probably need you to run:


and add the dkim TXT records gets added to the dns manually based on /etc/virtual/

It takes out the ---- lines and all newline characters when adding it to dns.

For domain created after this is all setup, this does not need to be called manually.

Note, the absence of the key won't break anything... so you may want to hold off on the hostname key until more testing has been done.

To test your DKIM setup, see check this tool: new will be very similar to, same values, etc..

Custom scripts for email creation/deletion/password changing

called once for each email account that is being deleted.

Auto-logout upon session expiry. (SKINS) new

When a session expires, the User is logged out.

A browser that is left open will be redirected to /CMD_LOGOUT for security reasons, as well as to prevent any image hover-over issues that can cause the ip to blacklisted if the browser tries to redownload images after the session is expired.



inserted in the <head> section:

<script language="JavaScript">
//timer for auto-logout
  function log_me_out()
    location.href = '/CMD_LOGOUT';
  setTimeout('log_me_out();', |SESSION_MINUTES|*60*1000);
// -->

better form checking for SRV records fixed

Ensure proper value checking for SRV records.


This change will ensure values are valid:

Use named-checkzone to better filter dns records

Saves us from having to learn all dns syntax. We'll let named tell us if it's valid.

secure_access_group default to 750 instead of 710 fixed

secure_access_group default to 750 instead of 710 so that .htaccess files can be read if they're in the domains directory.

This only applies to Admin/Reseller accounts.

The /home/user path will still be 710 for User accounts.

Enforce full format A record name to have zone value fixed

If an A record is being added to a zone, and the name is in the full format (ends in a period), this check will ensure that the name of the record being added ends in the name of the zone (prevents cache poisoning)

This check will not be enforced at the Admin Level dns management section, only User Level.

If a server Admin really wants to do this, they're more than welcome to.

Table class sorting fixed

When using the advanced search, if filtering result, remove the filtered data from the table before sorting and generating the table.

This will prevent strange sorting issues, and will result in correct page numbering.

Also add all filter/searches to also compare using html safe characters.

This is because a lot of table data is already html encoded, so when doing a comparison, it will only match if the value being searched for is also encoded.

Underscore in database names fixed

Either prevent _ character in database names (the User defined part), or escape them:


as this may be causing issues when DA is doing wildcard _ searches.

Also added the block to database usernames as well.

Note, in 1.40.0, an option was added to allow an override to this change:

option to allow underscores in db names and db users and are not called with restore fixed and are not called with restore.

They should be.

variables, similar to the other database_create_pre/ will be:


Note that user, passwd and system_password will be blank ("") as their plaintext values will not be known.

The login_as value will be set to 2, which will let you know this is a database creation via a restore.

The for restores is called right after the database is created. Users and access hosts will not yet exist.

If a database already exists at the time of the restore, the pre and post code will not be called.

Make email delivery stat less confusing fixed

Change "deliveries" to "sent" emails, and make the number of inbound emails onto a new row.

The sum of in/out together isn't as relevant for clients as just the singular numbers for in and out separately.

Also, the "Max Usage" row for "Sent Emails" will still be from:


however, if you've got the new, it supports:


which allows an override for any users who might need to send more.

DA will use this value if it exists in the "Max Usage" row for "Sent Emails"

If it doesn't exist, the default limit file will be used.

.htaccess files are 600 for redirects (unable to reproduce) fixed

.htaccess files need to be 644 and not 600.

Current workaround:

chmod 644 .htaccess

Bug possibly caused by changed with this fix:

existing .htaccess files breaking with addition of password protection

After investigation, I was not able to reproduce the bug on CentOS, FreeBSD or Debian systems.

Not sure what variables caused it (possibly human variable)

For safe measure, called a chmod 644 on the .htaccess after write to ensure it's set, bug or not.

Also set 644 for index.html files within newly created subdomain directories.

awstats for deleted subdomains not deleted fixed



is deleted when the is deleted.

The "Remove Directory Contents" option must be chosen or this won't take effect.

MySQL Users not being deleted fixed

When a MySQL User is being deleted, DA is removing the User from the mysql.db table, but isn't being removed from the mysql.user table if more than 1 access host is used, so Users are not able to re-add the User to the database, as DA would complain that it already exists. If you only have "localhost", then you shouldn't be affected by this. Solution was to add "AND host='localhost'" when doing the count of rows of that User on all databases (because if deleting the user from 1 db, then we delete completely. If the user exists on other DB's, we only remove it from the row of that db, and leave it in the other db lists)

Forced domain suspensions unsuspended on reset fixed

Users have the ability to suspend their domains. Another way a domain can be suspended if for bandwidth over-usage (limit set by the User for that domain).

This is not related to User limits and User suspension.

The issue is that when the monthly bandwidth reset happens, DA doesn't know how the domain became suspended, thus assumes it was for bandwidth over-usage, thus the domain is unsuspended. This may not be an intended behavior if the domain was actually suspended by choice by the User.

Fix is to use add an option:


option to:


This will only be set to 'no' if the User suspends the domain by hand.

If the domain is suspended by bandwidth, the value


will be used.

Either way, if a domain is suspended:


will be present.

When the reset happens, if active=no is used, the domain will not be unsuspended.

IPv4/6 swapping doesn't change record type in dns zones fixed

When changing the IP of a User, the code successfully changes the IPs in the dns db file.

However, if you're swapping from IPv4 to IPv6, or from IPv6 to IPv4, the code failed to also change the record type from A to AAAA, or vice versa.

Added code to check all A and AAAA records, and put them in their correct place if they're not after the ip swsp has completed.

Last Updated: