~clint-fewbar/ubuntu/precise/erlang/merge-15b

« back to all changes in this revision

Viewing changes to lib/kernel/src/inet_parse.erl

  • Committer: Bazaar Package Importer
  • Author(s): Clint Byrum
  • Date: 2011-05-05 15:48:43 UTC
  • mfrom: (3.5.13 sid)
  • Revision ID: james.westby@ubuntu.com-20110505154843-0om6ekzg6m7ugj27
Tags: 1:14.b.2-dfsg-3ubuntu1
* Merge from debian unstable.  Remaining changes:
  - Drop libwxgtk2.8-dev build dependency. Wx isn't in main, and not
    supposed to.
  - Drop erlang-wx binary.
  - Drop erlang-wx dependency from -megaco, -common-test, and -reltool, they
    do not really need wx. Also drop it from -debugger; the GUI needs wx,
    but it apparently has CLI bits as well, and is also needed by -megaco,
    so let's keep the package for now.
  - debian/patches/series: Do what I meant, and enable build-options.patch
    instead.
* Additional changes:
  - Drop erlang-wx from -et
* Dropped Changes:
  - patches/pcre-crash.patch: CVE-2008-2371: outer level option with
    alternatives caused crash. (Applied Upstream)
  - fix for ssl certificate verification in newSSL: 
    ssl_cacertfile_fix.patch (Applied Upstream)
  - debian/patches/series: Enable native.patch again, to get stripped beam
    files and reduce the package size again. (build-options is what
    actually accomplished this)
  - Remove build-options.patch on advice from upstream and because it caused
    odd build failures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
%%
2
2
%% %CopyrightBegin%
3
 
%% 
4
 
%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
5
 
%% 
 
3
%%
 
4
%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
 
5
%%
6
6
%% The contents of this file are subject to the Erlang Public License,
7
7
%% Version 1.1, (the "License"); you may not use this file except in
8
8
%% compliance with the License. You should have received a copy of the
9
9
%% Erlang Public License along with this software. If not, it can be
10
10
%% retrieved online at http://www.erlang.org/.
11
 
%% 
 
11
%%
12
12
%% Software distributed under the License is distributed on an "AS IS"
13
13
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
14
%% the License for the specific language governing rights and limitations
15
15
%% under the License.
16
 
%% 
 
16
%%
17
17
%% %CopyrightEnd%
18
18
%%
19
19
-module(inet_parse).
20
20
 
21
21
%% Parser for all kinds of ineternet configuration files
22
22
 
 
23
%% Avoid warning for local function error/2 clashing with autoimported BIF.
 
24
-compile({no_auto_import,[error/2]}).
23
25
-export([hosts/1, hosts/2]).
24
26
-export([hosts_vxworks/1]).
25
27
-export([protocols/1, protocols/2]).
34
36
-export([nsswitch_conf/1, nsswitch_conf/2]).
35
37
 
36
38
-export([ipv4_address/1, ipv6_address/1]).
 
39
-export([ipv4strict_address/1, ipv6strict_address/1]).
37
40
-export([address/1]).
38
41
-export([visible_string/1, domain/1]).
39
42
-export([ntoa/1, dots/1]).
456
459
 
457
460
 
458
461
%%
459
 
%% Test ipv4 address or ipv6 address
 
462
%% Parse ipv4 address or ipv6 address
460
463
%% Return {ok, Address} | {error, Reason}
461
464
%%
462
465
address(Cs) when is_list(Cs) ->
463
466
    case ipv4_address(Cs) of
464
 
        {ok,IP} -> {ok,IP};
 
467
        {ok,IP} ->
 
468
            {ok,IP};
465
469
        _ ->
466
 
            case ipv6_address(Cs) of
467
 
                {ok, IP} -> {ok, IP};
468
 
                Error -> Error
469
 
            end
 
470
            ipv6strict_address(Cs)
470
471
    end;
471
472
address(_) -> 
472
473
    {error, einval}.
477
478
%%    d1.d2.d4
478
479
%%    d1.d4
479
480
%%    d4
 
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.
480
485
%%
481
486
%% Return {ok, IP} | {error, einval}
482
487
%%
483
488
ipv4_address(Cs) ->
484
 
    case catch ipv4_addr(Cs) of
485
 
        {'EXIT',_} -> {error,einval};
486
 
        Addr -> {ok,Addr}
487
 
    end.
488
 
 
489
 
ipv4_addr(Cs) -> 
490
 
    ipv4_addr(d3(Cs), []).
491
 
 
492
 
ipv4_addr({Cs0,[]}, A) when length(A) =< 3 ->
493
 
    case [tod(Cs0)|A] of
494
 
        [D4,D3,D2,D1] ->
495
 
            {D1,D2,D3,D4};
496
 
        [D4,D2,D1] ->
497
 
            {D1,D2,0,D4};
498
 
        [D4,D1] ->
499
 
            {D1,0,0,D4};
500
 
        [D4] ->
501
 
            {0,0,0,D4}
502
 
    end;
503
 
ipv4_addr({Cs0,"."++Cs1}, A) when length(A) =< 2 ->
504
 
    ipv4_addr(d3(Cs1), [tod(Cs0)|A]).
505
 
 
506
 
d3(Cs) -> d3(Cs, []).
507
 
 
508
 
d3([C|Cs], R) when C >= $0, C =< $9, length(R) =< 2 ->
509
 
    d3(Cs, [C|R]);
510
 
d3(Cs, [_|_]=R) ->
511
 
    {lists:reverse(R),Cs}.
512
 
 
513
 
tod(Cs) ->
514
 
    case erlang:list_to_integer(Cs) of
515
 
        D when D >= 0, D =< 255 ->
516
 
            D;
517
 
        _ ->
518
 
            erlang:error(badarg, [Cs])
519
 
    end.
520
 
 
521
 
%%
522
 
%% Parse IPv6 address: 
 
489
    try ipv4_addr(Cs) of
 
490
        Addr ->
 
491
            {ok,Addr}
 
492
    catch
 
493
        error:badarg ->
 
494
            {error,einval}
 
495
    end.
 
496
 
 
497
ipv4_addr(Cs) ->
 
498
    case ipv4_addr(Cs, []) of
 
499
        [D] when D < (1 bsl 32) ->
 
500
            <<D1,D2,D3,D4>> = <<D:32>>,
 
501
            {D1,D2,D3,D4};
 
502
        [D,D1] when D < (1 bsl 24), D1 < 256 ->
 
503
            <<D2,D3,D4>> = <<D:24>>,
 
504
            {D1,D2,D3,D4};
 
505
        [D,D2,D1] when D < (1 bsl 16), (D2 bor D1) < 256 ->
 
506
            <<D3,D4>> = <<D:16>>,
 
507
            {D1,D2,D3,D4};
 
508
        [D4,D3,D2,D1] when (D4 bor D3 bor D2 bor D1) < 256 ->
 
509
            {D1,D2,D3,D4};
 
510
        _ ->
 
511
            erlang:error(badarg)
 
512
    end.
 
513
 
 
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).
 
525
 
 
526
ipv4_addr(Cs0, Ds, Rs, Base, N) ->
 
527
    case ipv4_field(Cs0, N, Rs, Base) of
 
528
        {D,""} ->
 
529
            [D|Ds];
 
530
        {D,[$.|[_|_]=Cs]} ->
 
531
            ipv4_addr(Cs, [D|Ds]);
 
532
        {_,_} ->
 
533
            erlang:error(badarg)
 
534
    end.
 
535
 
 
536
strip0("0"++Cs) ->
 
537
    strip0(Cs);
 
538
strip0(Cs) when is_list(Cs) ->
 
539
    Cs.
 
540
 
 
541
 
 
542
%%
 
543
%% Parse IPv4 strict dotted decimal address, no leading zeros:
 
544
%%    d1.d2.d3.d4
 
545
%%
 
546
%% Return {ok, IP} | {error, einval}
 
547
%%
 
548
ipv4strict_address(Cs) ->
 
549
    try ipv4strict_addr(Cs) of
 
550
        Addr ->
 
551
            {ok,Addr}
 
552
    catch
 
553
        error:badarg ->
 
554
            {error,einval}
 
555
    end.
 
556
 
 
557
ipv4strict_addr(Cs) ->
 
558
    case ipv4strict_addr(Cs, []) of
 
559
        [D4,D3,D2,D1] when (D4 bor D3 bor D2 bor D1) < 256 ->
 
560
            {D1,D2,D3,D4};
 
561
        _ ->
 
562
            erlang:error(badarg)
 
563
    end.
 
564
 
 
565
ipv4strict_addr([_|_], [_,_,_,_]) ->
 
566
    %% Early bailout for extra characters
 
567
    erlang:error(badarg);
 
568
ipv4strict_addr("0", Ds) ->
 
569
    [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
 
574
        {D,""} ->
 
575
            [D|Ds];
 
576
        {D,[$.|[_|_]=Cs]} ->
 
577
            ipv4strict_addr(Cs, [D|Ds]);
 
578
        {_,_} ->
 
579
            erlang:error(badarg)
 
580
    end.
 
581
 
 
582
 
 
583
 
 
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).
 
594
 
 
595
ipv4_field(Rs, Base) ->
 
596
    V = erlang:list_to_integer(lists:reverse(Rs), Base),
 
597
    if  V < 0 ->
 
598
            erlang:error(badarg);
 
599
        true ->
 
600
            V
 
601
    end.
 
602
 
 
603
 
 
604
 
 
605
%%
 
606
%% Forgiving IPv6 address
 
607
%%
 
608
%% Accepts IPv4 address and returns it as a IPv4 compatible IPv6 address
 
609
%%
 
610
ipv6_address(Cs) ->
 
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}};
 
614
        _ ->
 
615
            ipv6strict_address(Cs)
 
616
    end.
 
617
 
 
618
%%
 
619
%% Parse IPv6 address according to RFC 4291:
523
620
%%     x1:x2:x3:x4:x5:x6:x7:x8
524
621
%%     x1:x2::x7:x8
525
622
%%     ::x7:x8
530
627
%%     ::x5:x6:d7a.d7b.d8a.d8b
531
628
%%     x1:x2::d7a.d7b.d8a.d8b
532
629
%%     ::d7a.d7b.d8a.d8b
 
630
%%     etc
533
631
%%
534
632
%% Return {ok, IP} | {error, einval}
535
633
%%
536
 
ipv6_address(Cs) ->
537
 
    case catch ipv6_addr(Cs) of
538
 
        {'EXIT',_} -> {error,einval};
539
 
        Addr -> {ok,Addr}
 
634
ipv6strict_address(Cs) ->
 
635
    try ipv6_addr(Cs) of
 
636
        Addr ->
 
637
            {ok,Addr}
 
638
    catch
 
639
        error:badarg ->
 
640
            {error,einval}
540
641
    end.
541
642
 
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);
546
647
ipv6_addr(Cs) ->
547
 
    ipv6_addr(x4(Cs), []).
 
648
    ipv6_addr(hex(Cs), [], 0).
548
649
 
549
650
%% Before "::"
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).
560
663
 
561
664
%% After "::"
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)]).
568
 
 
569
 
%% After "."
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]).
574
 
 
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]).
577
 
 
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).
 
673
 
 
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).
 
676
 
 
677
ipv6_addr_done(Ar, Br, N) ->
 
678
    ipv6_addr_done(Br++dup(8-N, 0, Ar)).
580
679
 
581
680
ipv6_addr_done(Ar) ->
582
681
    list_to_tuple(lists:reverse(Ar)).
583
682
 
584
 
x4(Cs) -> x4(Cs, []).
585
 
 
586
 
x4([C|Cs], R) when C >= $0, C =< $9, length(R) =< 3 ->
587
 
    x4(Cs, [C|R]);
588
 
x4([C|Cs], R) when C >= $a, C =< $f, length(R) =< 3 ->
589
 
    x4(Cs, [C|R]);
590
 
x4([C|Cs], R) when C >= $A, C =< $F, length(R) =< 3 ->
591
 
    x4(Cs, [C|R]);
592
 
x4(Cs, [_|_]=R) ->
593
 
    {lists:reverse(R),Cs}.
594
 
 
595
 
tox(Cs) ->
596
 
    erlang:list_to_integer(Cs, 16).
597
 
 
 
683
%% Collect Hex digits
 
684
hex(Cs) -> hex(Cs, []).
 
685
%%
 
686
hex([C|Cs], R) when C >= $0, C =< $9 ->
 
687
    hex(Cs, [C|R]);
 
688
hex([C|Cs], R) when C >= $a, C =< $f ->
 
689
    hex(Cs, [C|R]);
 
690
hex([C|Cs], R) when C >= $A, C =< $F ->
 
691
    hex(Cs, [C|R]);
 
692
hex(Cs, [_|_]=R) when is_list(Cs) ->
 
693
    {lists:reverse(R),Cs};
 
694
hex(_, _) ->
 
695
    erlang:error(badarg).
 
696
 
 
697
%% Hex string to integer
 
698
hex_to_int(Cs0) ->
 
699
    case strip0(Cs0) of
 
700
        Cs when length(Cs) =< 4 ->
 
701
            erlang:list_to_integer("0"++Cs, 16);
 
702
        _ ->
 
703
            erlang:error(badarg)
 
704
    end.
 
705
 
 
706
%% Dup onto head of existing list
598
707
dup(0, _, L) ->
599
708
    L;
600
709
dup(N, E, L) when is_integer(N), N >= 1 ->
601
 
    dup(N-1, E, [E|L]);
602
 
dup(N, E, L) ->
603
 
    erlang:error(badarg, [N,E,L]).
 
710
    dup(N-1, E, [E|L]).
 
711
 
 
712
 
604
713
 
605
714
%% Convert IPv4 adress to ascii
606
715
%% Convert IPv6 / IPV4 adress to ascii (plain format)
674
783
    lists:reverse(R, [H]).
675
784
 
676
785
%% convert to A.B decimal form
677
 
dig_to_dec(0) -> [$0,$.,$0];
 
786
dig_to_dec(0) -> "0.0";
678
787
dig_to_dec(X) -> 
679
788
    integer_to_list((X bsr 8) band 16#ff) ++ "." ++
680
789
        integer_to_list(X band 16#ff).