b908ff46d07cd7761026bde9e3cf60e8bc5f09e6
3 require "$Bin/json_pp.pm";
16 print STDERR "command: $cmd\n";
20 sub fetch_active_data_linux($$) {
24 open DATA, "(ip -4 r s dev $ifname; ip -6 r s dev $ifname) |";
28 my @data = split /\s+/, $_;
29 next if $data[0] =~ /^fe80:/;
30 next if $data[0] =~ /^ff..:/;
31 $data[0] =~ /(:|\/)/ or do {
34 $data->{route}->{$data[0]} = 'delete';
38 open DATA, "ip a s dev $ifname |";
42 my @data = split /\s+/, $_;
43 next unless $data[0] =~ /inet/;
44 next if $data[1] =~ /^fe80:/;
45 $data->{ipaddr}->{$data[1]} = 'delete';
50 sub fetch_active_data_darwin($$) {
54 open DATA, "netstat -rn |";
58 my @data = split /\s+/, $_;
59 next unless $data[3] eq $ifname;
60 next if $data[0] =~ /^fe80:/;
61 next if $data[0] =~ /^ff..:/;
62 $data[0] =~ /(:|\/)/ or do {
64 my @addr = split /\./, $data[0];
69 $data[0] = join(".", @addr)."/$mask";
71 $data->{route}->{$data[0]} = 'delete';
75 open DATA, "ifconfig $ifname |";
79 my @data = split /\s+/, $_;
80 next unless $data[0] =~ /inet/;
81 next if $data[1] =~ /^fe80:/;
82 $data->{ipaddr}->{$data[1]} = 'delete';
87 sub update_data($$$) {
92 return unless $data->{"link-up"} eq 1;
93 foreach my $val (@{$data->{ipaddr}}, @{$data->{ip6addr}}) {
94 my $ip = $val->{ipaddr};
95 my $mask = $val->{mask};
99 if (not($ip =~ /::/) and $mask eq 64) {
100 $route =~ s/((\w+):(\w+):(\w+):(\w+)):.*/$1::/;
104 push @{$data->{routes6}}, { target => "$route", "netmask" => $mask };
106 push @{$data->{routes}}, { target => "$ip", "netmask" => 32 };
108 if ($delete->{ipaddr}->{$ip}) {
109 delete $delete->{ipaddr}->{$ip};
110 } elsif ($delete->{ipaddr}->{"$ip/$mask"}) {
111 delete $delete->{ipaddr}->{"$ip/$mask"};
113 $add->{ipaddr}->{"$ip/$mask"} = 'add';
116 foreach my $val (@{$data->{routes}}, @{$data->{routes6}}) {
117 my $ip = $val->{target}.'/'.$val->{netmask};
119 if ($delete->{route}->{$ip}) {
120 delete $delete->{route}->{$ip};
122 $add->{route}->{$ip} = 'add';
127 sub set_active_data_linux($$$) {
132 (keys %{$add->{ipaddr}}, keys %{$add->{route}}) > 0 and cmd("ip l s dev $ifname up");
134 foreach my $ip (keys %{$delete->{ipaddr}}) {
135 cmd("ip a d $ip dev $ifname");
137 foreach my $route (keys %{$delete->{route}}) {
138 cmd("ip r d $route dev $ifname");
141 foreach my $ip (keys %{$add->{ipaddr}}) {
142 cmd("ip a a $ip dev $ifname");
144 foreach my $route (keys %{$add->{route}}) {
145 cmd("ip r a $route dev $ifname");
149 sub set_active_data_darwin($$$) {
154 foreach my $ip (keys %{$delete->{ipaddr}}) {
157 cmd("ifconfig $ifname inet6 delete $ip");
159 cmd("ifconfig $ifname delete $ip");
162 foreach my $route (keys %{$delete->{route}}) {
164 cmd("route delete -inet6 $route -iface $ifname");
166 cmd("route delete -inet $route -iface $ifname");
169 foreach my $ip (keys %{$add->{ipaddr}}) {
170 my @ip = split /\//, $ip;
173 cmd("ifconfig $ifname inet6 add $ip[0] prefixlen $ip[1]");
175 cmd("ifconfig $ifname add $ip[0]/$ip[1] $ip[0]");
178 foreach my $route (keys %{$add->{route}}) {
180 cmd("route add -inet6 $route -iface $ifname");
182 cmd("route add -inet $route -iface $ifname");
188 my $platform = `uname`;
189 my $data = JSON::PP::decode_json($json) or die "Failed to decode JSON data\n";
191 my $delete = create_state();
192 my $add = create_state();
194 if ($platform =~ /Darwin/) {
195 fetch_active_data_darwin($data->{ifname}, $delete);
196 } elsif ($platform =~ /Linux/) {
197 fetch_active_data_linux($data->{ifname}, $delete);
199 die "Unsupported platform $platform\n";
202 update_data($data, $delete, $add);
204 if ($platform =~ /Darwin/) {
205 set_active_data_darwin($data->{ifname}, $delete, $add);
206 } elsif ($platform =~ /Linux/) {
207 set_active_data_linux($data->{ifname}, $delete, $add);
210 # print Data::Dumper->Dump([$add, $delete], ["add", "delete"])."\n";