Package: ddclient / 3.8.3-1.1

usev6.diff Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
Description: Add ipv6 support for dyndns
 This adds a "usev6" variable to ddclient to support IPv6 updates
 with dyndns and freedns.

Author: Eduardo TrĂ¡pani <etrapani@gmail.com>
Forwarded: no
Bug-Debian: https://bugs.debian.org/704467

---
 ddclient |   73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 67 insertions(+), 6 deletions(-)

--- a/ddclient
+++ b/ddclient
@@ -55,6 +55,7 @@ sub T_FILE	{'file name'};
 sub T_FQDNP	{'fully qualified host name and optional port number'};
 sub T_PROTO	{'protocol'}
 sub T_USE	{'ip strategy'}
+sub T_USEV6	{'ipv6 strategy'}
 sub T_IF        {'interface'}
 sub T_PROG      {'program name'}
 sub T_IP        {'ip'}
@@ -330,6 +331,7 @@ my %variables = (
 	'protocol'            => setv(T_PROTO, 0, 0, 1, 'dyndns2',            undef),
 
 	'use'                 => setv(T_USE,   0, 0, 1, 'ip',                 undef),
+	'usev6'               => setv(T_USEV6, 0, 0, 1, undef,                undef),
 	'ip'                  => setv(T_IP,    0, 0, 1, undef,                undef),
 	'if'                  => setv(T_IF,    0, 0, 1, 'ppp0',               undef),
 	'if-skip'             => setv(T_STRING,1, 0, 1, '',                   undef),
@@ -370,6 +372,7 @@ my %variables = (
 	'host'                => setv(T_STRING, 1, 1, 1, '',                  undef),
 
 	'use'                 => setv(T_USE,   0, 0, 1, 'ip',                 undef),
+	'usev6'               => setv(T_USE,   0, 0, 1, undef,                undef),
 	'if'                  => setv(T_IF,    0, 0, 1, 'ppp0',               undef),
 	'if-skip'             => setv(T_STRING,0, 0, 1, '',                   undef),
 	'web'                 => setv(T_STRING,0, 0, 1, 'dyndns',             undef),
@@ -597,7 +600,8 @@ my @opt = (
     [ "cache",       "=s", "-cache path           : record address used in 'path'" ],
     [ "pid",         "=s", "-pid path             : record process id in 'path'" ],
     "",			     
-    [ "use",         "=s", "-use which            : how the should IP address be obtained." ],
+    [ "use",         "=s", "-use which            : how should the IP address be obtained." ],
+    [ "usev6",       "=s", "-usev6 which          : how should the IPv6 address be obtained." ],
                                                   &ip_strategies_usage(),
     "",			     
     [ "ip",          "=s", "-ip address           : set the IP address to 'address'" ],
@@ -788,12 +792,20 @@ sub update_nics {
 		my (@hosts, %ips) = ();
 		my $updateable = $services{$s}{'updateable'};
 		my $update     = $services{$s}{'update'};
+		my $ipv6 = 0;
 
 		foreach my $h (sort keys %config) {
 			next if $config{$h}{'protocol'} ne lc($s);
 			$examined{$h} = 1;
 			# we only do this once per 'use' and argument combination
-			my $use = opt('use', $h);
+			my $use = '';
+			$ipv6 = 1 if (defined $config{$h}{'usev6'});
+			if ($ipv6) {
+				$use = opt('usev6', $h);
+			}
+			else {
+				$use = opt('use', $h);
+			}
 			my $arg_ip = opt('ip', $h) || '';
 			my $arg_fw = opt('fw', $h) || '';
 			my $arg_if = opt('if', $h) || '';
@@ -803,16 +815,20 @@ sub update_nics {
 			if (exists $iplist{$use}{$arg_ip}{$arg_fw}{$arg_if}{$arg_web}{$arg_cmd}) {
 				$ip = $iplist{$use}{$arg_ip}{$arg_fw}{$arg_if}{$arg_web}{$arg_cmd};
 			} else {
-				$ip = get_ip($use, $h);
+				$ip = get_ip($use, $h) if !$ipv6;
+				$ip = get_ipv6($use, $h) if $ipv6;
 				if (!defined $ip || !$ip) {
 					warning("unable to determine IP address")
 						if !$daemon || opt('verbose');
 					next;
 				}
-				if ($ip !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
+				if (!$ipv6 and $ip !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
 					warning("malformed IP address (%s)", $ip);
 					next;
 				}
+				if ($ipv6 and $ip !~ /^[0-9a-f:]+$/) {
+					warning("malformed IPv6 address (%s)", $ip);
+				}
 				$iplist{$use}{$arg_ip}{$arg_fw}{$arg_if}{$arg_web}{$arg_cmd} = $ip;
 			}
 			$config{$h}{'wantip'} = $ip;
@@ -953,7 +969,7 @@ sub parse_assignment {
     my ($c, $name, $value);
     my ($escape, $quote) = (0, '');
 
-    if ($rest =~ /^\s*([a-z][a-z_-]*)=(.*)/i) {
+    if ($rest =~ /^\s*([a-z][0-9a-z_-]*)=(.*)/i) {
 	($name, $rest, $value) = ($1, $2, '');
 
 	while (length($c = substr($rest,0,1))) {
@@ -1131,6 +1147,11 @@ sub init_config {
     $opt{'use'} = 'if'  if !define($opt{'use'}) && defined($opt{'if'});
     $opt{'use'} = 'web' if !define($opt{'use'}) && defined($opt{'web'});
 
+    ## infer the IPv6 strategy if possible
+    $opt{'usev6'} = 'ip'  if !define($opt{'usev6'}) && defined($opt{'ip'});
+    $opt{'usev6'} = 'if'  if !define($opt{'usev6'}) && defined($opt{'if'});
+    $opt{'usev6'} = 'web' if !define($opt{'usev6'}) && defined($opt{'web'});
+
     ## sanity check
     $opt{'max-interval'}       = min(interval(opt('max-interval')), interval(default('max-interval')));
     $opt{'min-interval'}       = max(interval(opt('min-interval')), interval(default('min-interval')));
@@ -1740,6 +1761,10 @@ sub check_value {
 	$value = lc $value;
 	return undef if ! exists $ip_strategies{$value};
 
+    } elsif ($type eq T_USEV6) {
+	$value = lc $value;
+	return undef if ! exists $ip_strategies{$value};
+
     } elsif ($type eq T_FILE) {
 	return undef if $value eq "";
 
@@ -1756,7 +1781,7 @@ sub check_value {
 #	return undef if $value =~ /:/;
 
     } elsif ($type eq T_IP) {
-	return undef if $value !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
+	return undef if $value !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ and $value !~ /^[0-9a-f:]+$/;
     }
     return $value;
 }
@@ -2046,6 +2071,42 @@ sub get_ip {
 	$ip = $1;
     }
     if (($use ne 'ip') && (define($ip,'') eq '0.0.0.0')) {
+	$ip = undef;
+    }
+
+    debug("get_ip: using %s, %s reports %s", $use, $arg, define($ip, "<undefined>"));
+    return $ip;
+}
+
+######################################################################
+## get_ipv6
+######################################################################
+sub get_ipv6 {
+    my $use = lc shift;
+    my $h = shift;
+    my ($ip, $arg, $reply, $url, $skip) = (undef, opt($use), '');
+    $arg = '' unless $arg;
+
+    if ($use eq 'ip') {
+	$ip  = opt('ip', $h);
+	$arg = 'ip';
+
+    } elsif ($use eq 'if') {
+	$skip  = opt('if-skip', $h)  || '';
+	$reply = `ip -6 addr list dev "$arg" scope global -tentative -deprecated  -dadfailed | grep inet6 | grep -v temporary | grep -v "inet6 f[cd]" 2> /dev/null`;
+	$reply = '' if $?;
+    }
+    if (!defined $reply) {
+	$reply = '';
+    }
+    if ($skip) {
+	$skip  =~ s/ /\\s/is;
+    	$reply =~ s/^.*?${skip}//is;
+    }
+    if ($reply =~ /.*? ([0-9:][^\/]*)/i) {
+	$ip = $1;
+    }
+    if (($use ne 'ip') && (define($ip,'') eq '0.0.0.0')) {
 	$ip = undef;
     }