481
%% Any d may be octal, hexadecimal or decimal by C language standards.
482
%% d4 fills all LSB bytes. This is legacy behaviour from Solaris
483
%% and FreeBSD. And partly Linux that behave the same except
484
%% it does not accept hexadecimal.
481
486
%% Return {ok, IP} | {error, einval}
483
488
ipv4_address(Cs) ->
484
case catch ipv4_addr(Cs) of
485
{'EXIT',_} -> {error,einval};
490
ipv4_addr(d3(Cs), []).
492
ipv4_addr({Cs0,[]}, A) when length(A) =< 3 ->
503
ipv4_addr({Cs0,"."++Cs1}, A) when length(A) =< 2 ->
504
ipv4_addr(d3(Cs1), [tod(Cs0)|A]).
506
d3(Cs) -> d3(Cs, []).
508
d3([C|Cs], R) when C >= $0, C =< $9, length(R) =< 2 ->
511
{lists:reverse(R),Cs}.
514
case erlang:list_to_integer(Cs) of
515
D when D >= 0, D =< 255 ->
518
erlang:error(badarg, [Cs])
522
%% Parse IPv6 address:
498
case ipv4_addr(Cs, []) of
499
[D] when D < (1 bsl 32) ->
500
<<D1,D2,D3,D4>> = <<D:32>>,
502
[D,D1] when D < (1 bsl 24), D1 < 256 ->
503
<<D2,D3,D4>> = <<D:24>>,
505
[D,D2,D1] when D < (1 bsl 16), (D2 bor D1) < 256 ->
506
<<D3,D4>> = <<D:16>>,
508
[D4,D3,D2,D1] when (D4 bor D3 bor D2 bor D1) < 256 ->
514
ipv4_addr([_|_], [_,_,_,_]) ->
515
%% Early bailout for extra characters
516
erlang:error(badarg);
517
ipv4_addr("0x"++Cs, Ds) ->
518
ipv4_addr(strip0(Cs), Ds, [], 16, 8);
519
ipv4_addr("0X"++Cs, Ds) ->
520
ipv4_addr(strip0(Cs), Ds, [], 16, 8);
521
ipv4_addr("0"++Cs, Ds) ->
522
ipv4_addr(strip0(Cs), Ds, [$0], 8, 11);
523
ipv4_addr(Cs, Ds) when is_list(Cs) ->
524
ipv4_addr(Cs, Ds, [], 10, 10).
526
ipv4_addr(Cs0, Ds, Rs, Base, N) ->
527
case ipv4_field(Cs0, N, Rs, Base) of
531
ipv4_addr(Cs, [D|Ds]);
538
strip0(Cs) when is_list(Cs) ->
543
%% Parse IPv4 strict dotted decimal address, no leading zeros:
546
%% Return {ok, IP} | {error, einval}
548
ipv4strict_address(Cs) ->
549
try ipv4strict_addr(Cs) of
557
ipv4strict_addr(Cs) ->
558
case ipv4strict_addr(Cs, []) of
559
[D4,D3,D2,D1] when (D4 bor D3 bor D2 bor D1) < 256 ->
565
ipv4strict_addr([_|_], [_,_,_,_]) ->
566
%% Early bailout for extra characters
567
erlang:error(badarg);
568
ipv4strict_addr("0", Ds) ->
570
ipv4strict_addr("0."++Cs, Ds) ->
571
ipv4strict_addr(Cs, [0|Ds]);
572
ipv4strict_addr(Cs0, Ds) when is_list(Cs0) ->
573
case ipv4_field(Cs0, 3, [], 10) of
577
ipv4strict_addr(Cs, [D|Ds]);
584
ipv4_field("", _, Rs, Base) ->
585
{ipv4_field(Rs, Base),""};
586
ipv4_field("."++_=Cs, _, Rs, Base) ->
587
{ipv4_field(Rs, Base),Cs};
588
ipv4_field("0"++_, _, [], _) ->
589
erlang:error(badarg);
590
ipv4_field([C|Cs], N, Rs, Base) when N > 0 ->
591
ipv4_field(Cs, N-1, [C|Rs], Base);
592
ipv4_field(Cs, _, _, _) when is_list(Cs) ->
593
erlang:error(badarg).
595
ipv4_field(Rs, Base) ->
596
V = erlang:list_to_integer(lists:reverse(Rs), Base),
598
erlang:error(badarg);
606
%% Forgiving IPv6 address
608
%% Accepts IPv4 address and returns it as a IPv4 compatible IPv6 address
611
case ipv4_address(Cs) of
612
{ok,{D1,D2,D3,D4}} ->
613
{ok,{0,0,0,0,0,16#ffff,(D1 bsl 8) bor D2,(D3 bsl 8) bor D4}};
615
ipv6strict_address(Cs)
619
%% Parse IPv6 address according to RFC 4291:
523
620
%% x1:x2:x3:x4:x5:x6:x7:x8
530
627
%% ::x5:x6:d7a.d7b.d8a.d8b
531
628
%% x1:x2::d7a.d7b.d8a.d8b
532
629
%% ::d7a.d7b.d8a.d8b
534
632
%% Return {ok, IP} | {error, einval}
537
case catch ipv6_addr(Cs) of
538
{'EXIT',_} -> {error,einval};
634
ipv6strict_address(Cs) ->
542
643
ipv6_addr("::") ->
543
ipv6_addr_done([], []);
644
ipv6_addr_done([], [], 0);
544
645
ipv6_addr("::"++Cs) ->
545
ipv6_addr(x4(Cs), [], []);
646
ipv6_addr(hex(Cs), [], [], 0);
547
ipv6_addr(x4(Cs), []).
648
ipv6_addr(hex(Cs), [], 0).
550
ipv6_addr({Cs0,[]}, A) when length(A) =:= 7 ->
551
ipv6_addr_done([tox(Cs0)|A]);
552
ipv6_addr({Cs0,"::"}, A) when length(A) =< 6 ->
553
ipv6_addr_done([tox(Cs0)|A], []);
554
ipv6_addr({Cs0,"::"++Cs1}, A) when length(A) =< 5 ->
555
ipv6_addr(x4(Cs1), [tox(Cs0)|A], []);
556
ipv6_addr({Cs0,":"++Cs1}, A) when length(A) =< 6 ->
557
ipv6_addr(x4(Cs1), [tox(Cs0)|A]);
558
ipv6_addr({Cs0,"."++Cs1}, A) when length(A) =:= 6 ->
559
ipv6_addr(d3(Cs1), A, [], [tod(Cs0)]).
651
ipv6_addr({Cs0,[]}, A, N) when N == 7 ->
652
ipv6_addr_done([hex_to_int(Cs0)|A]);
653
ipv6_addr({Cs0,"::"}, A, N) when N =< 6 ->
654
ipv6_addr_done([hex_to_int(Cs0)|A], [], N+1);
655
ipv6_addr({Cs0,"::"++Cs1}, A, N) when N =< 5 ->
656
ipv6_addr(hex(Cs1), [hex_to_int(Cs0)|A], [], N+1);
657
ipv6_addr({Cs0,":"++Cs1}, A, N) when N =< 6 ->
658
ipv6_addr(hex(Cs1), [hex_to_int(Cs0)|A], N+1);
659
ipv6_addr({Cs0,"."++_=Cs1}, A, N) when N == 6 ->
660
ipv6_addr_done(A, [], N, ipv4strict_addr(Cs0++Cs1));
661
ipv6_addr(_, _, _) ->
662
erlang:error(badarg).
562
ipv6_addr({Cs0,[]}, A, B) when length(A)+length(B) =< 6 ->
563
ipv6_addr_done(A, [tox(Cs0)|B]);
564
ipv6_addr({Cs0,":"++Cs1}, A, B) when length(A)+length(B) =< 5 ->
565
ipv6_addr(x4(Cs1), A, [tox(Cs0)|B]);
566
ipv6_addr({Cs0,"."++Cs1}, A, B) when length(A)+length(B) =< 5 ->
567
ipv6_addr(x4(Cs1), A, B, [tod(Cs0)]).
570
ipv6_addr({Cs0,[]}, A, B, C) when length(C) =:= 3 ->
571
ipv6_addr_done(A, B, [tod(Cs0)|C]);
572
ipv6_addr({Cs0,"."++Cs1}, A, B, C) when length(C) =< 2 ->
573
ipv6_addr(d3(Cs1), A, B, [tod(Cs0)|C]).
575
ipv6_addr_done(Ar, Br, [D4,D3,D2,D1]) ->
576
ipv6_addr_done(Ar, [((D3 bsl 8) bor D4),((D1 bsl 8) bor D2)|Br]).
578
ipv6_addr_done(Ar, Br) ->
579
ipv6_addr_done(Br++dup(8-length(Ar)-length(Br), 0, Ar)).
665
ipv6_addr({Cs0,[]}, A, B, N) when N =< 6 ->
666
ipv6_addr_done(A, [hex_to_int(Cs0)|B], N+1);
667
ipv6_addr({Cs0,":"++Cs1}, A, B, N) when N =< 5 ->
668
ipv6_addr(hex(Cs1), A, [hex_to_int(Cs0)|B], N+1);
669
ipv6_addr({Cs0,"."++_=Cs1}, A, B, N) when N =< 5 ->
670
ipv6_addr_done(A, B, N, ipv4strict_addr(Cs0++Cs1));
671
ipv6_addr(_, _, _, _) ->
672
erlang:error(badarg).
674
ipv6_addr_done(Ar, Br, N, {D1,D2,D3,D4}) ->
675
ipv6_addr_done(Ar, [((D3 bsl 8) bor D4),((D1 bsl 8) bor D2)|Br], N+2).
677
ipv6_addr_done(Ar, Br, N) ->
678
ipv6_addr_done(Br++dup(8-N, 0, Ar)).
581
680
ipv6_addr_done(Ar) ->
582
681
list_to_tuple(lists:reverse(Ar)).
584
x4(Cs) -> x4(Cs, []).
586
x4([C|Cs], R) when C >= $0, C =< $9, length(R) =< 3 ->
588
x4([C|Cs], R) when C >= $a, C =< $f, length(R) =< 3 ->
590
x4([C|Cs], R) when C >= $A, C =< $F, length(R) =< 3 ->
593
{lists:reverse(R),Cs}.
596
erlang:list_to_integer(Cs, 16).
683
%% Collect Hex digits
684
hex(Cs) -> hex(Cs, []).
686
hex([C|Cs], R) when C >= $0, C =< $9 ->
688
hex([C|Cs], R) when C >= $a, C =< $f ->
690
hex([C|Cs], R) when C >= $A, C =< $F ->
692
hex(Cs, [_|_]=R) when is_list(Cs) ->
693
{lists:reverse(R),Cs};
695
erlang:error(badarg).
697
%% Hex string to integer
700
Cs when length(Cs) =< 4 ->
701
erlang:list_to_integer("0"++Cs, 16);
706
%% Dup onto head of existing list
600
709
dup(N, E, L) when is_integer(N), N >= 1 ->
603
erlang:error(badarg, [N,E,L]).
605
714
%% Convert IPv4 adress to ascii
606
715
%% Convert IPv6 / IPV4 adress to ascii (plain format)