#!/usr/bin/perl -wT # gsutil - GrandStream configuration dump/restore + reboot # Copyright (C) 2006 Charles Howes # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. $main::VERSION="3.0"; # 2006-07-27 use strict; use Getopt::Std; use HTML::Form; use HTTP::Request; use LWP::UserAgent; use Socket; use POSIX qw(strftime); use Data::Dumper; # Backup the command line: my $cmdline=join(" ",@ARGV); # Stuff used by getopts: $Getopt::Std::STANDARD_HELP_VERSION=1; # Get command line options: my %opts; my $r=getopts('bdehnop:r',\%opts); # If the user is asking for help: if (defined $opts{'h'}) { VERSION_MESSAGE(*STDOUT{IO}); HELP_MESSAGE(*STDOUT{IO}); exit 0; } # Version information, called by getopts if --version or --help given. sub VERSION_MESSAGE { my $fh=$_[0]; # Passed a file handle. print $fh "Version $main::VERSION of GSutil, a GrandStream BudgeTone phone backup, restore\n"; print $fh "and reboot utility. Written by Charles Howes (gsutil\@ch.pkts.ca).\n"; print $fh "http://www.pkts.ca/gsutil.shtml\n"; } # Help information, called by getopts if --help given. sub HELP_MESSAGE { my $fh=$_[0]; # Passed a file handle. print $fh "Usage: $0 -[b|d|e|h|r] [-n] [-o] [-p password] address..\n"; print $fh " -b : reboot\n"; print $fh " -d : dump to stdout\n"; print $fh " -e : show phone firmware versions\n"; print $fh " -r : restore from stdin\n"; print $fh " -n : don't wait for reboot to finish\n"; print $fh " -o : don't translate configuration values\n"; print $fh " -p : password (default: admin)\n"; print $fh " -h, --help : print this help\n"; print $fh " --version : print the version of gsutil\n"; # getopts exits after calling HELP_MESSAGE() } if (!defined $opts{'b'} and !defined $opts{'d'} and !defined $opts{'e'} and !defined $opts{'r'}) { print STDERR "No command was given.\n\n"; print STDERR "Choose one of -b, -d, -e, or -r to do something.\n"; print STDERR "Try `$0 --help' for more information.\n"; exit 0; } # Get the password my $password=$opts{'p'}; if (!defined $password) {$password='admin'}; # Default password # The addresses are on the command line: if (!defined $ARGV[0]) { print STDERR "No addresses of phones were given on the command line.\n"; HELP_MESSAGE(*STDOUT{IO}); exit(3); } # Convert and error-check all hosts: my @todo=map {parseaddress($_)} @ARGV; # The configuration variables get translated into english with this table. # The translations themselves are stored in the __DATA__ block at the end. my %translate; my %untranslate; while () { chomp; s/#.*//; # remove comments s/\s+$//; # remove trailing space # if no translation is available, use the key: if (/^\s*(P\d+):\s*(.*)/) { $translate{$1} = $2; $untranslate{uc($2)} = $1; } } # Lines of data from stdin my $linenumber=0; # For each host on the command line: foreach my $address (@todo) { # Set up the user agent: my $ua=LWP::UserAgent->new(timeout=>3); my $url="http://$address/"; # Get the login page: my $req_login=HTTP::Request->new(GET=>$url); my $resp_login=$ua->request($req_login); if ($resp_login->code != 200) { show_error($address,$resp_login); next;} my $form_login=HTML::Form->parse($resp_login->content,$url); if (!defined $form_login) { warn("$address didn't respond with a form; is it a GS phone?\n"); next; } # See if this is the right form if (grep(/^P2$/,$form_login->param)==0) { warn("$address The form didn't have the expected 'P2' (password) field in it!\n". " Debug output:\n".Dumper($form_login)); next; } # Stuff in the password $form_login->value('P2' => $password); # Log in and get main page my $resp_main = $ua->request($form_login->click); if ($resp_main->code != 200 or $resp_main->content =~ m/Your Login Password is not recognized/) { show_error($address,$resp_main); next;} my $form_main=HTML::Form->parse($resp_main->content,$form_login->action); # Find the cookie: my $cookie=$resp_main->headers->header("set-cookie"); #1.0.5.x:'set-cookie' => 'SessionId=3bf1ca965d26edb9"; Version=1; Path=/' #1.0.6.x:'set-cookie' => 'SessionId="965c22e1bd86fece"; Version=1; Path=/' if (!defined $cookie) { warn("$address No cookie was sent, but the password was accepted?! This may be a new firmware.\n"); next; } if ($cookie!~m/SessionId="?([^"]*)"/) { warn("$address The cookie didn't contain 'SessionId'! This may be a new firmware.\n". " It said: $cookie\n"); next; } my $sessionid=$1; # Get everything: my $domore=0; my $resp_index_htm=$ua->request(HTTP::Request->new(GET=>$url."index.htm",HTTP::Headers->new(Cookie=>"SessionID=\"$sessionid\""))); my $resp_config2_htm=$ua->request(HTTP::Request->new(GET=>$url."config2.htm",HTTP::Headers->new(Cookie=>"SessionID=\"$sessionid\""))); # Get extended phone configuration if your firmware supports it: my $resp_config_a1_htm=$ua->request(HTTP::Request->new(GET=>$url."config_a1.htm",HTTP::Headers->new(Cookie=>"SessionID=\"$sessionid\""))); if ($resp_config_a1_htm->code==200) {$domore=1;} # Do a2-a4 only if a1 was found. my $resp_config_a2_htm=$domore?$ua->request(HTTP::Request->new(GET=>$url."config_a2.htm",HTTP::Headers->new(Cookie=>"SessionID=\"$sessionid\""))):undef; my $resp_config_a3_htm=$domore?$ua->request(HTTP::Request->new(GET=>$url."config_a3.htm",HTTP::Headers->new(Cookie=>"SessionID=\"$sessionid\""))):undef; my $resp_config_a4_htm=$domore?$ua->request(HTTP::Request->new(GET=>$url."config_a4.htm",HTTP::Headers->new(Cookie=>"SessionID=\"$sessionid\""))):undef; # Do everything: if (defined $opts{'e'}) { show_version($address,$resp_main,$resp_index_htm); } if (defined $opts{'d'}) { dump_data($address,$resp_main,$resp_index_htm,$resp_config2_htm,$resp_config_a1_htm,$resp_config_a2_htm,$resp_config_a3_htm,$resp_config_a4_htm); } if (defined $opts{'r'}) { restore_data($address,$sessionid,$resp_main,$resp_index_htm,$resp_config2_htm,$resp_config_a1_htm,$resp_config_a2_htm,$resp_config_a3_htm,$resp_config_a4_htm); } if (defined $opts{'b'}) { reboot($address,$url,$sessionid,$opts{'n'}); } } # Show the phone's hardware model and version: sub show_version { my ($address,$resp_main,$resp_index_htm)=@_; my $body=$resp_main->content.$resp_index_htm->content; my $model; my $version; if ($body=~m/Product Model:\s*<\/b><\/td>\s*([^<]*)/s) { $model=$1; $model=~s/( |\s+)/ /gs; $model=~s/(^\s+)|(\s+$)//gs; } if ($body=~m/Software Version:\s*<\/b><\/td>\s*([^<]*)/s) { $version=$1; $version=~s/( |\s+)/ /gs; # delete spaces and   $version=~s/(^\s+)|(\s+$)//gs; # delete leading/trailing spaces $version=~s/\s+/ /gs; # delete spaces some more $version=~s/--/:/gs; # turn -- into : } my $head="# $address"; if (defined $model) {print $head." Model ".$model;$head="";} if (defined $version) {print $head." ".$version;$head="";} if ($head eq "") {print "\n";} } # Reboot the phone: sub reboot { my ($address,$url,$sessionid,$opts_n)=@_; my $ua2=LWP::UserAgent->new(timeout=>1); my $resp_rs_htm=$ua2->request(HTTP::Request->new(GET=>$url."rs.htm",HTTP::Headers->new(Cookie=>"SessionID=\"$sessionid\""))); if (!defined $opts_n) { my $req_login=HTTP::Request->new(GET=>$url); my $resp_login; my $now=time(); my $up=1; for (my $n=0;$n<30;$n++) { # Should be done in 21 seconds or so. $resp_login=$ua2->request($req_login); if ($resp_login->code==200 and $up==1) {sleep(1);next;} if ($resp_login->code==500) {$up=0;next;} last; # It's up again after being down (200 -> 500 -> 200) # Note, if pppoe is configured, it could go down again for a bit. } } } # Dump the phone configuration to stdout: sub dump_data { my ($address,@responses)=@_; my $stamp=strftime("%Y-%m-%d %H:%M:%S",localtime()); print "#-- start of phone $address ($stamp)\n"; # Mark the start foreach (@responses) { if (defined $_) {dump_form($address,HTML::Form->parse($_));} } print "#-- end of phone $address ($stamp)\n"; } # Restre the phone configuration from stdin: sub restore_data { my ($address,$sessionid,@responses)=@_; my %val; # Error checking: my %formlines; my %filled; # Read stdinput for the phone's data: while() { chomp; $linenumber++; if (m/^#-- end of phone/) {last;} # End of this phone's configuration if (m/^#/) {next;} # Skip comment lines if (m/^$/) {next;} # Skip blank lines s/\s+#.*//; # Comment deletion (won't cut in the middle of a word) if (m/^([^=]+)=(.*)$/) { # name = value... my $ls=$1; # ls=left side my $rs=$2; # rs=right side # Trim whitespace, uppercase ls: $ls=~s/^\s*(.*?)\s*$/\U$1/; $rs=~s/^\s*(.*?)\s*$/$1/; # Quote removal from rs: $rs=~s/^'(.*)'$/$1/; $rs=~s/^"(.*)"$/$1/; # Stick it into %val: if (defined($translate{$ls})) { $val{$ls}=$rs;next;} # P999 = ... if (defined($untranslate{$ls})) { $val{$untranslate{$ls}}=$rs;next;} # name = ... warn("$address Unknown input variable '$_', from stdin line $linenumber.\n Add it to the translation table at the end of the program.\n"); } warn("$address Unrecognized input line '$_', from stdin line $linenumber\n"); } # Fill in the form(s): my $form; my $ua2=LWP::UserAgent->new(timeout=>3); foreach my $response (@responses) { if (!defined $response) {next;} # No response here (a2-a4?) $form=HTML::Form->parse($response); if (!defined $form) {next;} # No form here (a1?) foreach my $n ($form->param) { $formlines{$n}=1; # These fields were present on the phone if (defined $val{$n}) { $form->param($n,$val{$n}); $filled{$n}=1; # These fields were filled in from stdin } } # Make the request and add a cookie: my $request=$form->make_request; $request->header("Cookie" => "SessionId=\"$sessionid\""); # Send it: my $response=$ua2->request($request); } # Check for missed data: foreach (sort keys %val) { if (!defined $formlines{$_}) { warn("$address The config file had $_ ($translate{$_}), but the phone did not.\n"); } } } # Print out the fields and their values: sub dump_form { my ($address,$form) = @_; if (!defined $form) {return;} # Deal with undefined forms foreach my $n ($form->param) { if ($n =~ m/^(cancel|reboot|gnkey|update|P2|P196)$/) {next;} if (defined $translate{$n} && !defined $opts{'o'}) { print $translate{$n}," = ",$form->param($n),"\n"; } else { if (!defined $opts{'o'}) { warn("$address The parameter $n(=".($form->param($n)).") was not found in the translate table.\n Use -o to skip translation, or manually add it to the translate table\n"); } if (defined $translate{$n}) { print "# $translate{$n}:\n"; } print "$n = ",$form->param($n),"\n"; print "\n"; } } } # Convert addresses given on command line, and check them. sub parseaddress { my $add=$_[0]; if ($add !~ m/^([a-z0-9.-]{1,80})$/) { # Valid characters? warn("$add isn't a valid hostname\n"); return; } my $address=$1; if ($address=~m/[a-z]/) { # If it has a letter, it's a hostname if (!defined gethostbyname($address)) { warn("$address unknown host\n"); return; } } return $address; } # Decode the error message sub show_error { my ($address,$response)=@_; if (!defined $response) { die("$0: show_error called with not enough arguments"); } # Page not found: if ($response->code == 403) { warn("$address page not found, is this a GS phone?\n"); return; } # Bad password: if ($response->content =~ m/Your Login Password is not recognized/) { $cmdline =~ s/\s+-p\s*\S+//; # Cut out old password warn("$address bad password.\n". " Try: $0 -p your-secret-password $cmdline\n"); return; } # Error: if ($response->code == 500) { # Trying to connect to a firewalled, misconfigured or dead phone: if ($response->content =~ m/Can't connect to \S+ \(connect: timeout\)/) { warn("$address was unreachable (either rebooting, firewalled, misconfigured, unplugged, or dead)\n"); return; } # The arp table knows how to get there, but the phone is not answering: if ($response->content =~ m/Can't connect to \S+ \(connect: No route to host\)/) { warn("$address was unreachable (either rebooting or recently unplugged)\n"); return; } # The phone is tired of being queried over and over: if ($response->content =~ m/read timeout/) { warn("$address gave a read timeout after connecting; try again.\n"); return; } } # Some other fatal error: warn("$address gave an unexpected ".($response->code)." error.\n". " Here is a full dump of the response:\n". Dumper($response)."\n". " Send this to the author, gsutil\@ch.pkts.ca\n". " so that it can be added to the program.\n" ); return; } # This is the translate table: __DATA__ P2: admin_password P3: name P8: static_ipaddress_true P9: static_ipaddress_1 P10: static_ipaddress_2 P11: static_ipaddress_3 P12: static_ipaddress_4 P13: static_subnet_1 P14: static_subnet_2 P15: static_subnet_3 P16: static_subnet_4 P17: static_router_1 P18: static_router_2 P19: static_router_3 P20: static_router_4 P21: static_dns1_1 P22: static_dns1_2 P23: static_dns1_3 P24: static_dns1_4 P25: static_dns2_1 P26: static_dns2_2 P27: static_dns2_3 P28: static_dns2_4 P29: early_dial P30: ntp_server P31: sip_registration P32: register_expiration P33: voicemail_userid P34: authenticate_password P35: sip_userid P36: authenticate_id P37: voice_frames_per_tx P38: layer3_QoS P39: local_rtp_port P40: local_sip_port P41: tftp_server_1 P42: tftp_server_2 P43: tftp_server_3 P44: tftp_server_4 P46: vocoder_7 P47: sip_server P48: outbound_proxy P49: G723_rate P50: silence_suppression P51: layer2_QoS_vlan_tag P52: nat_traversal_true P57: vocoder_1 P58: vocoder_2 P59: vocoder_3 P60: vocoder_4 P61: vocoder_5 P62: vocoder_6 P63: userid_is_phone_number P64: time_zone P65: send_anonymous P66: dial_plan_prefix P71: offhook_autodial P72: use_hash_as_dial_key P73: send_dtmf_mode P74: send_flash_event P75: daylight_savings_time P76: nat_traversal_stun_server P78: use_random_port P79: dtmf_payload_type P81: unregister_on_reboot P82: PPPoE_id P83: PPPoE_password P84: keepalive_interval P85: no_key_entry_timeout P86: FXS_impedance P87: layer2_QoS_priority_value P88: lock_keypad_update P90: auto_answer P91: disable_call_waiting P92: dhcp_dns_server_1 P93: dhcp_dns_server_2 P94: dhcp_dns_server_3 P95: dhcp_dns_server_4 P96: iLBC_payload_type P97: iLBC_frame_size P98: vocoder_8 P99: subscribe_for_mwi P101: use_nat_ip P102: date_display_format P103: use_dns_srv P104: default_ring_tone P105: custom_ring_tone_1_caller_id P106: custom_ring_tone_2_caller_id P107: custom_ring_tone_3_caller_id P109: allow_out_call_without_registration # 0 or 1 P110: lan_subnet_mask P111: lan_dhcp_base_ip P112: dhcp_ip_lease_time P113: dmz_ip P115: cloned_wan_mac_addr_1 P116: cloned_wan_mac_addr_2 P117: cloned_wan_mac_addr_3 P118: cloned_wan_mac_addr_4 P119: cloned_wan_mac_addr_5 P120: cloned_wan_mac_addr_6 P122: time_display_format # 0 = 12 hour; 1 = 24 hour P123: display_clock_instead_of_date # 0 or 1 P143: dhcp_option_2_timezone_override P144: dhcp_option_42_timeserver_override P145: dhcp_option_66_bootserver P146: dhcp_option_12_hostname # ppoe_hostname P147: dhcp_option_15_domain # ppoe_domain_name P148: dhcp_option_60_vendor_class_id # ppoe_vendor_class P150: port_fw_port_num_1 P151: port_fw_port_num_2 P152: port_fw_port_num_3 P153: port_fw_port_num_4 P154: port_fw_port_num_5 P155: port_fw_port_num_6 P156: port_fw_port_num_7 P157: port_fw_port_num_8 P158: port_fw_lan_ip_1 P159: port_fw_lan_ip_2 P160: port_fw_lan_ip_3 P161: port_fw_lan_ip_4 P162: port_fw_lan_ip_5 P163: port_fw_lan_ip_6 P164: port_fw_lan_ip_7 P165: port_fw_lan_ip_9 P166: port_fw_lan_port_1 P167: port_fw_lan_port_2 P168: port_fw_lan_port_3 P169: port_fw_lan_port_4 P170: port_fw_lan_port_5 P171: port_fw_lan_port_6 P172: port_fw_lan_port_7 P173: port_fw_lan_port_8 P174: port_fw_lan_proto_1 P175: port_fw_lan_proto_2 P176: port_fw_lan_proto_3 P177: port_fw_lan_proto_4 P178: port_fw_lan_proto_5 P179: port_fw_lan_proto_6 P180: port_fw_lan_proto_7 P181: port_fw_lan_proto_8 P182: disable_missed_calls_1 P184: use_quick_ip_call_mode P189: replay_to_icmp_in_wan # 0 = no # 1 = yes P190: wan_side_http_access # 0 = no # 1 = yes P191: enable_call_features P192: http_upgrade_url P193: automatic_http_upgrade_days P194: automatic_http_upgrade P196: end_user_password P197: proxy_require P198: special_feature_1 # 100 = Standard # 101 = Nortel MCS # 102 = Broadsoft # 103 = Howdy # 104 = Sonus # 105 = 3COM P200: caller_id_scheme P205: polarity_reversal P206: onhook_voltage P207: syslog_server P208: syslog_level P209: sip_t1_timeout # 50 = 0_5_sek # 100 = 1_sek # 200 = 2_sek P212: firmware_upgrade P213: firmware_upgrade_tftp_1 P214: firmware_upgrade_tftp_2 P215: firmware_upgrade_tftp_3 P216: firmware_upgrade_tftp_4 P228: fax_mode P231: device_mode # 0 = switch # 1 = nat_router P232: firmware_file_prefix P233: firmware_file_postfix P234: config_file_prefix P235: config_file_postfix P237: config_server_path P238: always_check_for_new_firmware P239: register_expiration_delay # in seconds, default 1800 P240: auth_config_file # 0 = No # 1 = Yes P241: allow_conf_sip_account_in_basic_settings # 0 or 1 P242: firmware_key # text (in Hexadecimal Representation) P243: allow_from_sip_proxy_only # 0 or 1 P244: override_mtu_size # 0 or 1 P245: onhook_threshold # 0 = Hookflash OFF # 2 = 200 ms # 4 = 400 ms # 6 = 600 ms # 8 = 800 ms (default) # 10 = 1000 ms # 12 = 1200 ms P250: sip_t2_interval P260: session_expiration_1 # in seconds, default 180 P261: min_session_expiration_1 # seconds, minimum 90 P262: caller_request_timer_1 # 0 or 1 P263: callee_request_timer_1 # 0 or 1 P264: force_timer_1 # 0 or 1 P265: force_invite_1 # 0 or 1 P266: uac_specify_refresher_1 # 0=omit, 1=UAC, 2=UAS P267: uas_specify_refresher_1 # 1=UAC, 2=UAS P268: anonymous_method # 0 = Use From Header (default) # 1 = Use Privacy Header P270: account_name_1 P271: account_active_1 # 0 or 1 P272: enable_100rel_1 # 0 or 1 P298: allow_auto_answer_by_call_info P299: turn_off_speaker_on_remote_disconnect P301: speed_dial_1_account # 0, 1, 2, 3 P302: speed_dial_1_name P303: speed_dial_1_userid P304: speed_dial_2_account P305: speed_dial_2_name P306: speed_dial_2_userid P307: speed_dial_3_account P308: speed_dial_3_name P309: speed_dial_3_userid P310: speed_dial_4_account P311: speed_dial_4_name P312: speed_dial_4_userid P313: speed_dial_5_account P314: speed_dial_5_name P315: speed_dial_5_userid P316: speed_dial_6_account P317: speed_dial_6_name P318: speed_dial_6_userid P319: speed_dial_7_account P320: speed_dial_7_name P321: speed_dial_7_userid P322: lcd_backlight_always_on # 0 or 1 P323: multi_purpose_key_1 # 0 = speed_dial # 1 = asterisk_blf P324: multi_purpose_key_2 # 0 = speed_dial # 1 = asterisk_blf P325: multi_purpose_key_3 # 0 = speed_dial # 1 = asterisk_blf P326: multi_purpose_key_4 # 0 = speed_dial # 1 = asterisk_blf P327: multi_purpose_key_5 # 0 = speed_dial # 1 = asterisk_blf P328: multi_purpose_key_6 # 0 = speed_dial # 1 = asterisk_blf P329: multi_purpose_key_7 # 0 = speed_dial # 1 = asterisk_blf P401: account_active_2 # 0 or 1 P402: sip_server_2 P403: outbound_proxy_2 P404: sip_userid_2 P405: authenticate_id_2 P406: authenticate_password_2 P407: name_2 P408: use_dns_srv_2 P409: userid_is_phone_number_2 P410: sip_registration_2 P411: unregister_on_reboot_2 P412: register_expiration_2 P413: local_sip_port_2 P414: nat_traversal_true_2 P415: subscribe_for_mwi_2 P416: send_dtmf_2 # 0=in-audio, 1=RTP (RFC2833), 2=SIP INFO P417: account_name_2 P418: proxy_require_2 P419: dial_plan_prefix_2 P420: enable_call_features_2 P421: send_anonymous_2 P422: early_dial_2 P423: account_ring_tone_2 # 0, 1, 2, 3 P424: special_feature_2 # 100 = Standard # 101 = Nortel MCS # 102 = Broadsoft # 103 = Howdy # 104 = Sonus # 105 = 3COM P425: auto_answer_2 P426: voicemail_userid_2 P427: min_session_expiration_2 P428: caller_request_timer_2 P429: callee_request_timer_2 P430: force_timer_2 P431: force_invite_2 P432: uac_specify_refresher_2 P433: uas_specify_refresher_2 P434: session_expiration_2 P435: enable_100rel_2 P438: allow_auto_answer_by_caller_info P439: turn_off_speaker_on_remote_disconnect P440: sip_t1_imeout P441: sip_t2_interval P442: disable_missed_calls_2 P451: vocoder_1_2 P452: vocoder_2_2 P453: vocoder_3_2 P454: vocoder_4_2 P455: vocoder_5_2 P456: vocoder_6_2 P457: vocoder_7_2 P458: vocoder_8_2 P501: account_active_3 # 0 or 1 P502: sip_server_3 P503: outbound_proxy_3 P504: sip_userid_3 P505: authenticate_id_3 P506: authenticate_password_3 P507: name_3 P508: use_dns_srv_3 P509: userid_is_phone_number_3 P510: sip_registration_3 P511: unregister_on_reboot_3 P512: register_expiration_3 P513: local_sip_port_3 P514: nat_traversal_true_3 P515: subscribe_for_mwi_3 P516: send_dtmf_3 # 0=in-audio, 1=RTP (RFC2833), 2=SIP INFO P517: account_name_3 P518: proxy_require_3 P519: dial_plan_prefix_3 P520: enable_call_features_3 P521: send_anonymous_3 P522: early_dial_3 P523: account_ring_tone_3 # 0, 1, 2, 3 P524: special_feature_3 # 100 = Standard # 101 = Nortel MCS # 102 = Broadsoft # 103 = Howdy # 104 = Sonus # 105 = 3COM P525: auto_answer_3 P526: voicemail_userid_3 P527: min_session_expiration_3 P528: caller_request_timer_3 P529: callee_request_timer_3 P530: force_timer_3 P531: force_invite_3 P532: uac_specify_refresher_3 P533: uas_specify_refresher_3 P534: session_expiration_3 P535: enable_100rel_3 P538: allow_auto_answer_by_caller_info P539: turn_off_speaker_on_remote_disconnect P540: sip_t1_imeout P541: sip_t2_interval P542: disable_missed_calls_3 P551: vocoder_1_3 P552: vocoder_2_3 P553: vocoder_3_3 P554: vocoder_4_3 P555: vocoder_5_3 P556: vocoder_6_3 P557: vocoder_7_3 P558: vocoder_8_3 P601: account_active_4 # 0 or 1 P602: sip_server_4 P603: outbound_proxy_4 P604: sip_userid_4 P605: authenticate_id_4 P606: authenticate_password_4 P607: name_4 P608: use_dns_srv_4 P609: userid_is_phone_number_4 P610: sip_registration_4 P611: unregister_on_reboot_4 P612: register_expiration_4 P613: local_sip_port_4 P614: nat_traversal_true_4 P615: subscribe_for_mwi_4 P616: send_dtmf_4 # 0=in-audio, 1=RTP (RFC2833), 2=SIP INFO P617: account_name_4 P618: proxy_require_4 P619: dial_plan_prefix_4 P620: enable_call_features_4 P621: send_anonymous_4 P622: early_dial_4 P623: account_ring_tone_4 # 0, 1, 2, 3 P624: special_feature_4 # 100 = Standard # 101 = Nortel MCS # 102 = Broadsoft # 103 = Howdy # 104 = Sonus # 105 = 3COM P625: auto_answer_4 P626: voicemail_userid_4 P627: min_session_expiration_4 P628: caller_request_timer_4 P629: callee_request_timer_4 P630: force_timer_4 P631: force_invite_4 P632: uac_specify_refresher_4 P633: uas_specify_refresher_4 P634: session_expiration_4 P635: enable_100rel_4 P638: allow_auto_answer_by_caller_info P639: turn_off_speaker_on_remote_disconnect P640: sip_t1_imeout P641: sip_t2_interval P642: disable_missed_calls_4 P651: vocoder_1_4 P652: vocoder_2_4 P653: vocoder_3_4 P654: vocoder_4_4 P655: vocoder_5_4 P656: vocoder_6_4 P657: vocoder_7_4 P658: vocoder_8_4 # Handle BT200 with firmware 1.1.6.16 P129: annon_call_rejection P1301: headset_tx_gain P1302: headset_rx_gain P130: sip_transport P131: symmetric_routing P135: refer-to_use_target_contact P137: disable_multiple_media_attribute_in_sdp P138: SIP_Registration_Failure_Retry_Wait_Time P139: Delayed_Call_Forward_Wait_Time P183: SRTP_Mode P187: Disable_Call_Log P246: optional_rule P258: Check_SIP_User_ID_for_incoming_INVITE P336: mute_speaker_ringer P339: display_name_not_date P343: Dial_Tone P344: Message_Waiting P345: System_Ring_Tone P346: Ring_Back_Tone P347: Call_Waiting_Tone P348: Busy_Tone P349: Reorder_Tone # Handle GXP2000 with firmware 1.1.6.16 # P134: eventlist_BLF_URI_1 P186: Disable_Call-Waiting_Tone P188: PUBLISH_for_Presence P330: Enable_Phonebook_XML_Download P331: Phonebook_XML_Server_Path P332: Phonebook_Download_Interval P333: Remove_Manually-edited_entries_on_Download P338: Disable_in-call_DTMF_display P340: Enable_Idle_Screen_XML_Download P341: Idle_Screen_XML_Server_Path P342: Display_Language P351: Disable_Missed_Call_Backlight P399: Secondary_Language P443: SRTP_Mode_2 P444: eventlist_BLF_URI_2 P446: Anonymous_Call_Rejection_2 P447: Use_RFC3581_Symmetric_Routing_2 P448: SIP_Transport_2 P449: Check_SIP_User_ID_for_incoming_INVITE_2 P468: Anonymous_Method_2 P469: Refer-To_Use_Target_Contact_2 P470: Delayed_Call_Forward_Wait_Time_2 P471: SIP_Registration_Failure_Retry_Wait_Time_2 P487: Disable_Multiple_Media_Attribute_in_SDP_2 P488: PUBLISH_for_Presence_2 P543: SRTP_Mode_3 P544: eventlist_BLF_URI_3 P546: Anonymous_Call_Rejection_3 P547: Use_RFC3581_Symmetric_Routing_3 P548: SIP_Transport_3 P549: Check_SIP_User_ID_for_incoming_INVITE_3 P568: Anonymous_Method_3 P569: Refer-To_Use_Target_Contact_3 P570: Delayed_Call_Forward_Wait_Time_3 P571: SIP_Registration_Failure_Retry_Wait_Time_3 P587: Disable_Multiple_Media_Attribute_in_SDP_3 P588: PUBLISH_for_Presence_3 P643: SRTP_Mode_4 P644: eventlist_BLF_URI_4 P646: Anonymous_Call_Rejection_4 P647: Use_RFC3581_Symmetric_Routing_4 P648: SIP_Transport_4 P649: Check_SIP_User_ID_for_incoming_INVITE_4 P668: Anonymous_Method_4 P669: Refer-To_Use_Target_Contact_4 P670: Delayed_Call_Forward_Wait_Time_4 P671: SIP_Registration_Failure_Retry_Wait_Time_4 P687: Disable_Multiple_Media_Attribute_in_SDP_4 P688: PUBLISH_for_Presence_4 P1304: LDAP_Script_Server_Path P1310: Disable_Direct_IP_Calls P1311: Disable_Conference P1339: Enable_MPK_sending_DTMF P1340: Disable_DND P1328: Ring_Timeout_1 P1329: LCD_Contrast P476: Ring Timeout_2 P576: Ring Timeout_3 P676: Ring Timeout_4 # End of the file