/*_____________________________________________________________________________ |/ / UPnP NAT script by David "Saturn" van Moolenbroek | Version 0.1a, released 04-12-2005 -- support on #help.script/Quakenet | Use/modify however you want, but please keep my name in it. Thank you! | | Keywords: networking, COM | | This script allows you to add, delete and enumerate Network Address | Translation (NAT) entries of an Universal Plug'n'Play (UPnP) compatible | router or firewall. In order for this script to work, you need to have a | UPnP-compatible Windows version (e.g. Windows XP) and a UPnP NAT device. | | The script is based on the excellent work by Knox North; see his webpage at | http://www.knoxscape.com/Upnp/NAT.htm for more information on the subject. | | The script defines the following commands/identifiers: | | /upnp add | | Adds an entry to the UPnP NAT list. It takes a number of arguments: the | port number that is to be opened up at the outside (eport), the protocol | of the connections for this port (proto; either "TCP" or "UDP"), the | internal IP (iaddr) and port number (iport) to which incoming connections | on the external port and protocol should be forwarded, a flag value | (enabled; either "$true" or "$false") indicating whether this entry is | enabled, and a textual description of the entry (desc). You can also | replace the properties of existing entries with this command. | | /upnp del | | Deletes an entry from the UPnP NAT list, based on its external port | number and its protocol (TCP or UDP). | | /upnp list | | Lists the current UPnP NAT entries. | | $upnp(N) | | Properties: desc, eaddr, eport, iaddr, iport, proto, enabled | | This identifier returns information about entries in the UPnP NAT list. | If N is zero, it returns the number of entries in the list, otherwise it | returns a certain piece of information about the Nth entry. | | The following properties are available: "desc" returns the description of | the entry; "eaddr" returns the external IP address associated with the | entry (i.e. the IP address of the router); "eport" returns the port | number at which the router is accepting connections; "iaddr" and "iport" | are the address (IP or hostname) and port number of the internal address | to which those connections are forwarded; "proto" returns TCP or UDP | indicating what protocol the entry is for, and "enabled" returns $true or | $false depending on whether the entry is enabled. The "desc" property is | returned in case no other property is specified. | | If UPnP NAT is not available, the identifier will return $null on any | query. | | Note | | Both "/upnp list" and the $upnp identifier are currently (mIRC 6.16) | *DEAD SLOW*. This is because both mIRC and the UPnP NAT COM object | perform heaps of unnecessary extra work while enumerating the existing | connections with $comval(). There is little I can do about this, | hopefully at least newer mIRC versions will speed up the enumeration | process somewhat. | | Simple examples | | /upnp add 12345 tcp 192.168.1.2 12345 $true Test entry | /upnp del 12345 tcp \ _\_____________________________________________________________________________ */ ; Time (in seconds) after which the portmapping COM object will be closed alias -l upnp.timeout return 10 alias -l upnp.handle { if (.comclose * iswm $timer(upnpnat).com) { .timerupnpnat -io 1 $upnp.timeout $v2 return $gettok($v2,2,32) } var %n = nat $+ $ticks, %m = map $+ $ticks .comopen %n HNetCfg.NATUPnP var %r = $com(%n,StaticPortMappingCollection,3,dispatch* %m) .comclose %n if (!%r) || (!$com(%m)) return .timerupnpnat -io 1 $upnp.timeout .comclose %m return %m } alias -l upnp.get { if (!$2) return $iif($com($1,Count,3),$com($1).result) if ($findtok(desc eaddr eport iaddr iport proto enabled,$3,32)) $& return $comval($1,$2,$gettok(Description ExternalIPAddress $& ExternalPort InternalClient InternalPort Protocol Enabled,$v1,32)) } alias upnp { if ($isid) { if ($0 != 1) || ($1 !isnum 0-) return var %h = $upnp.handle if (!%h) return return $upnp.get(%h,$1,$iif($prop != $null,$v1,desc)) } if ($0) && ($findtok(add del list,$1,32) == $null) { echo -aeqc info * /upnp: invalid parameters return } if ($0 < $gettok(7 3 1,$v1,32)) { echo -aeqc info * /upnp: insufficient parameters return } if (($1 != list) && (($2 !isnum 1-65535) || (!$istok(TCP UDP,$3,32)))) || $& (($1 == add) && ($5 !isnum 1-65535)) { echo -aeqc info * /upnp: invalid parameters return } var %h = $upnp.handle if (%h == $null) { echo -aeqc info * /upnp: unable to access UPnP NAT return $false } if ($1 == add) { var %r = res $+ $ticks if (!$com(%h,Add,3,long,$2,bstr,$upper($3),long,$5,bstr,$4,bool,$6, $& bstr,$7-,dispatch* %r)) { echo -aeqc info * /upnp: unable to add UPnP NAT entry return $false } echo -aeqc info2 * Added UPnP NAT entry for $2 $+ / $+ $lower($3) .comclose %r return $true } elseif ($1 == del) { if (!$com(%h,Remove,3,long,$2,bstr,$upper($3))) { echo -aeqc info * /upnp: unable to delete UPnP NAT entry return $false } echo -aeqc info2 * Deleted UPnP NAT entry for $2 $+ / $+ $lower($3) return $true } else { var %i = 1, %n = $upnp.get(%h,0) if (!%n) { echo -aeqc info * No UPnP NAT entries found return } echo -aeqc info * UPnP NAT entries: while (%i <= %n) { echo -aqc info2 [[ $+ $iif($upnp.get(%h,%i,enabled),x,$chr(32)) $& $+ ]] $upnp.get(%h,%i,desc) $+ : $upnp.get(%h,%i,eport) -> $& $upnp.get(%h,%i,iaddr) $+ : $+ $upnp.get(%h,%i,iport) ( $+ $& $upnp.get(%h,%i,proto) $+ ) inc %i } linesep } }