@@ -376,12 +376,19 @@ Add the following directive to the module:
376376-type ip_address () :: ip4_address () | ip6_address ().
377377
378378-doc """
379- An IP address in text form, as accepted by the ` parse_* ` functions.
379+ An IP address in text form, as accepted by the
380+ [ ` parse_ ` * ] ( `parse_address/1` ) functions.
380381
381382Either a [ character list] ( `t:string/0` ) such as ` "192.168.0.1" ` ,
382383or a ` t:binary/0 ` such as ` ~"192.168.0.1" ` .
383384
384- * Since OTP @OTP-20357 @* a binary is accepted; before that only a list.
385+ > #### Note {: .info }
386+ >
387+ > * Since OTP @OTP-20357 @* a binary is accepted; before that only a list.
388+ >
389+ > With that change, the ` parse_ ` * functions mostly raise an error exception
390+ > for an argument that is not according to this type. Before this,
391+ > common bad arguments were handled and returned ` {error, einval} ` .
385392""" .
386393-type address_string () :: string () | binary ().
387394
@@ -2937,7 +2944,41 @@ net_getservbyname(Name, Protocol) when is_atom(Protocol) ->
29372944 net :getservbyname (Name , Protocol ).
29382945
29392946
2940- -doc " Parse an `t:ip_address/0` to an IPv4 or IPv6 address string." .
2947+ -doc """
2948+ Convert an ` t:ip_address/0 ` to an IPv4 or IPv6 address string.
2949+
2950+ The returned string, if parsed with ` parse_address/1 `
2951+ or ` parse_strict_address/1 ` will return the same ` IpAddress ` .
2952+
2953+ An ` t:ip4_address/0 ` returns a string in dot-decimal notation,
2954+ as described for ` parse_ipv4strict_address/1 ` .
2955+
2956+ An ` t:ip6_address/0 ` returns a string in the format
2957+ described for ` parse_ipv6strict_address/1 ` .
2958+
2959+ The first of the longest sequence of consecutive zeros
2960+ in the ` t:ip6_address/0 ` is compressed with ` "::" ` .
2961+
2962+ IPv4-Mapped and IPv4-Compatible IPv6 addresses are converted
2963+ to an address string with dot-decimal notation suffix.
2964+
2965+ A link-local unicast or multicast address that has a non-zero
2966+ second word (an embedded interface index), outputs that interface index
2967+ in a scope id suffix (a ` "%" ` char followed by a decimal integer string).
2968+
2969+ Examples:
2970+
2971+ ``` text
2972+ {127,0,0,1} -> "127.0.0.1"
2973+ {0,0,0,0,0,0,0,0} -> "::"
2974+ {8193,3512,0,0,8,2048,8204,16762} -> "2001:db8::8:800:200c:417a"
2975+ {0,0,0,0,0,65535,32512,1} -> "::ffff:127.0.0.1"
2976+ {0,0,0,0,0,0,32512,1} -> "::127.0.0.1"
2977+ {0,0,0,0,0,1,32512,1} -> "::1:7f00:1"
2978+ {65282,0,0,0,0,0,0,17} -> "ff02::11"
2979+ {65152,3,0,0,0,0,0,1} -> "fe80::1%3"
2980+ ```
2981+ """ .
29412982-doc (#{since => <<" OTP R16B02" >>}).
29422983-spec ntoa (IpAddress ) -> Address | {error , einval } when
29432984 Address :: string (),
@@ -2948,8 +2989,82 @@ ntoa(Addr) ->
29482989-doc """
29492990Parse (relaxed) an IPv4 address string to an ` t:ip4_address/0 ` .
29502991
2951- Accepts a short form IPv4 address string (less than 4 fields)
2952- such as ` "127.1" ` or ` "0x7f000001" ` .
2992+ The allowed formats are according to the documentation of
2993+ the libc function inet_aton(), the so called numbers-and-dots notation,
2994+ a fairly flexible format.
2995+
2996+ In short, the string shall have 1..4 dot separated fields.
2997+
2998+ Each field can be one of:
2999+ * A decimal number with at most ten digits, starting with one digit
3000+ ` "1" ` ..` "9" ` , and followed by decimal digits ` "0" ` ..` "9" ` .
3001+ * The decimal number ` "0" ` , also as according to
3002+ the following octal number rule:
3003+ * An octal number starting with ` "0" ` , followed by
3004+ at most eleven octal digits ` "0" ` ..` "7" ` .
3005+ * A hexadecimal number prefixed by ` "0x" ` or ` "0X" ` ,
3006+ followed by at most eight hexadecimal digits
3007+ ` "0" ` ..` "9" ` , ` "a" ` ..` "f" ` or ` "A" ` ..` "F" ` .
3008+
3009+ Note that decimal numbers cannot be written with leading zeros,
3010+ since that means octal numbers.
3011+
3012+ If there are 4 fields, ** A.B.C.D** , then all are bytes assigned in
3013+ left-to-right order. This corresponds to a legacy Class C
3014+ network address, for example ` "192.168.0.17" ` .
3015+
3016+ If there are 3 fields, ** A.B.C** , then ** A** and ** B** are the two
3017+ initial bytes, and ** C** is the 16 bit big endian value that follows.
3018+ This corresponds to a legacy Class B network address,
3019+ for example ` "172.16.4711" ` , which is equivalent to ` "172.16.18.103" ` .
3020+
3021+ If there are 2 fields, ** A.B** , then ** A** is the initial byte,
3022+ and ** B** is the 24 bit big endian value that follows.
3023+ This corresponds to a legacy Class A network address,
3024+ for example ` "10.174711" ` , which is equivalent to ` "10.2.170.119" ` .
3025+
3026+ If there is only 1 field it is a 32 bit big endian value.
3027+
3028+ In this notation all these strings represent the
3029+ ` t:ip4_address/0 ` ` {127,0,0,1} ` , where the first one is in
3030+ dot-decimal notation as accepted by ` parse_ipv4strict_address/1 `
3031+ and output by ` ntoa/1 ` , which is a stricter subset of the
3032+ numbers-and-dots notation parsed by this function.
3033+ ``` text
3034+ "127.0.0.1"
3035+ "127.0.1" % Class B 127.0.0.1
3036+ "127.1" % Class C 127.0.0.1
3037+ "0x7f000001" % Hexadecimal 32-bit
3038+ "0X7f.0.0.1" % Hexadecimal first byte
3039+ "0177.0.0.1" % Octal first byte
3040+ "0177.0000.0000.0001" % Leading zeros in octal fields
3041+ "0x7f.0x00.0x00.0x01" % Leading zeros in hexadecimal fields
3042+ ```
3043+
3044+ The description above implies that leading and trailing characters
3045+ are not allowed, and fields are not allowed to be empty.
3046+ So for example the following strings return ` {error, einval} ` :
3047+
3048+ ``` text
3049+ " 127.0.0.1" % Leading whitespace
3050+ "127.0.0.1\n" % Trailing whitespace
3051+ "127.0.0." % Empty field
3052+ ".0.0.0" % Empty field
3053+ "127..0.1" % Empty field
3054+ "x7f.0.0.1" % Malformed prefix
3055+ "127.0.0.x1" % Malformed prefix
3056+ "127.0.0.256" % Byte overflow
3057+ "127.0.65536" % 16-bit word overflow
3058+ "127.0x01000000" % 24-bit word overflow
3059+ ```
3060+
3061+ > #### Note {: .info }
3062+ >
3063+ > * Since OTP @OTP-20357 @* a binary is accepted; before that only a list.
3064+ >
3065+ > With that change, this function mostly raises an error exception
3066+ > for an argument that is of an invalid type. Before this,
3067+ > common bad arguments were handled and returned ` {error, einval} ` .
29533068""" .
29543069-doc (#{since => <<" OTP R16B" >>}).
29553070-spec parse_ipv4_address (Address ) ->
@@ -2962,8 +3077,25 @@ parse_ipv4_address(Addr) ->
29623077-doc """
29633078Parse (relaxed) an IPv6 address string to an ` t:ip6_address/0 ` .
29643079
2965- Also accepts a (relaxed) IPv4 address string like ` parse_ipv4_address/1 `
2966- and returns an IPv4-mapped IPv6 address.
3080+ "Relaxed" in this case means that if ` Address ` is
3081+ a "relaxed" IPv4 address string as accepted by ` parse_ipv4_address/1 ` ,
3082+ this function returns an IPv4-mapped IPv6 address.
3083+
3084+ Example: ` "127.0.0.1" ` gives ` {0,0,0,0,0,65535,32512,1} ` ,
3085+ as does ` "::ffff:127.0.0.1" `
3086+
3087+ Otherwise ` Address ` has to be an IPv6 address string
3088+ as accepted by ` parse_ipv6strict_address/1 ` .
3089+
3090+ Example: ` "2001::1" ` gives ` {8193,0,0,0,0,0,0,1} ` .
3091+
3092+ > #### Note {: .info }
3093+ >
3094+ > * Since OTP @OTP-20357 @* a binary is accepted; before that only a list.
3095+ >
3096+ > With that change, this function mostly raises an error exception
3097+ > for an argument that is of an invalid type. Before this,
3098+ > common bad arguments were handled and returned ` {error, einval} ` .
29673099""" .
29683100-doc (#{since => <<" OTP R16B" >>}).
29693101-spec parse_ipv6_address (Address ) ->
@@ -2976,8 +3108,41 @@ parse_ipv6_address(Addr) ->
29763108-doc """
29773109Parse an IPv4 address string to an ` t:ip4_address/0 ` .
29783110
2979- Requires an IPv4 address string containing four fields,
2980- that is; _ not_ a short form address string.
3111+ The allowed format is according to the documentation of
3112+ the libc function inet_pton(), the so called dot-decimal notation,
3113+ without leading zeros.
3114+
3115+ The string shall have 4 dot separated fields with decimal numbers
3116+ of 1..3 digits in the range 0..255. Leading zeros are not allowed,
3117+ which rules out the ambiguity whether a leading zero could mean octal notation.
3118+
3119+ These are some address strings that are successfully parsed:
3120+
3121+ ``` text
3122+ "0.0.0.0"
3123+ "127.0.0.1"
3124+ "255.255.255.255"
3125+ ```
3126+
3127+ As for ` parse_ipv4_address/1 ` leading and trailing characters
3128+ are not allowed.
3129+
3130+ Here are some examples of strings that return ` {error, einval} ` :
3131+
3132+ ``` text
3133+ " 0.0.0.0" % Leading whitespace
3134+ "0.0.0.0\n" % Trailing whitespace
3135+ "127.000.000.001" % Leading zeros
3136+ "127.0.0.256" % Byte overflow
3137+ ```
3138+
3139+ > #### Note {: .info }
3140+ >
3141+ > * Since OTP @OTP-20357 @* a binary is accepted; before that only a list.
3142+ >
3143+ > With that change, this function mostly raises an error exception
3144+ > for an argument that is of an invalid type. Before this,
3145+ > common bad arguments were handled and returned ` {error, einval} ` .
29813146""" .
29823147-doc (#{since => <<" OTP R16B" >>}).
29833148-spec parse_ipv4strict_address (Address ) ->
@@ -2990,9 +3155,51 @@ parse_ipv4strict_address(Addr) ->
29903155-doc """
29913156Parse an IPv6 address string to an ` t:ip6_address/0 ` .
29923157
2993- _ Doesn't_ accept an IPv4 address string. An IPv6 address string, though,
2994- allows an IPv4 tail like this: ` "::127.0.0.1" `
2995- (which is the same as ` "::7f00:0001" ` ).
3158+ Accepted address strings are those according to RFC 4291 section 2.2,
3159+ IP Version 6 Addressing Architecture - Text Representation of Addresses.
3160+
3161+ In short, and address string is 8 colon separated 1..4 hexadecimal
3162+ digits fields where leading zeros are allowed. One double colon
3163+ can be used to fill out the address with one or more zero fields.
3164+ The double colon is also allowed at the start and the end of the string.
3165+
3166+ Both the letters ` "a" ` ..` "f" ` and ` "A" ` ..` "F" ` are allowed
3167+ in the hexadecimal fields.
3168+
3169+ The last two fields can be expressed with IPv4 dot-decimal notation
3170+ as accepted by ` parse_ipv4strict_address/1 ` .
3171+
3172+ An address can have a suffix denoting the IPv6 scope id. It is
3173+ a ` "%" ` character followed by a non-empty string. If that string
3174+ is a decimal integer (leading zeros are allowed), the address
3175+ has to be a link-local unicast or multicast IPv6 address,
3176+ and then the decimal integer is embedded into the second field
3177+ of the address, which is supposed to be zero. This is the
3178+ FreeBSD approach of embedding a link index into a link-local IPv6 address.
3179+ Strings that are not decimal integers are currently ignored.
3180+
3181+ Examples:
3182+
3183+ ``` text
3184+ "2001:DB8:0:0:8:800:200C:417A"
3185+ "2001:db8::8:800:200c:417a"
3186+ "ff02:0:0:0:0:0:0:1010"
3187+ "ff02::1010"
3188+ "2000::"
3189+ "::"
3190+ "::1"
3191+ "::127.0.0.1"
3192+ "::ffff:192.168.0.53"
3193+ "fe80::1%3"
3194+ ```
3195+
3196+ > #### Note {: .info }
3197+ >
3198+ > * Since OTP @OTP-20357 @* a binary is accepted; before that only a list.
3199+ >
3200+ > With that change, this function mostly raises an error exception
3201+ > for an argument that is of an invalid type. Before this,
3202+ > common bad arguments were handled and returned ` {error, einval} ` .
29963203""" .
29973204-doc (#{since => <<" OTP R16B" >>}).
29983205-spec parse_ipv6strict_address (Address ) ->
@@ -3005,10 +3212,22 @@ parse_ipv6strict_address(Addr) ->
30053212-doc """
30063213Parse an IP address string to an ` t:ip_address/0 ` .
30073214
3008- Returns an ` t:ip4_address/0 ` or an ` t:ip6_address/0 ` depending
3009- on which parsing that succeeds .
3215+ First tries to parse the ` Address ` string with ` parse_ipv4_address/1 `
3216+ and if that returns ` {error, einval} ` with ` parse_ipv6strict_address/1 ` .
30103217
3011- Accepts a short form IPv4 address string like ` parse_ipv4_address/1 ` .
3218+ Hence this function accepts either an IPv4 address string in
3219+ numbers-and-dots notation, or an IPv6 address string.
3220+
3221+ Returns an ` t:ip4_address/0 ` or an ` t:ip6_address/0 `
3222+ depending on which parsing succeeds.
3223+
3224+ > #### Note {: .info }
3225+ >
3226+ > * Since OTP @OTP-20357 @* a binary is accepted; before that only a list.
3227+ >
3228+ > With that change, this function mostly raises an error exception
3229+ > for an argument that is of an invalid type. Before this,
3230+ > common bad arguments were handled and returned ` {error, einval} ` .
30123231""" .
30133232-doc (#{since => <<" OTP R16B" >>}).
30143233-spec parse_address (Address ) ->
@@ -3035,7 +3254,22 @@ parse_address(Addr, inet6) ->
30353254-doc """
30363255Parse an IP address string to an ` t:ip_address/0 ` .
30373256
3038- Like ` parse_address/1 ` but _ doesn't_ accept a short form IPv4 address string.
3257+ First tries to parse the ` Address ` string with ` parse_ipv4strict_address/1 `
3258+ and if that returns ` {error, einval} ` with ` parse_ipv6strict_address/1 ` .
3259+
3260+ Hence this function accepts either an IPv4 address string in
3261+ dot-decimal notation, or an IPv6 address string.
3262+
3263+ Returns an ` t:ip4_address/0 ` or an ` t:ip6_address/0 `
3264+ depending on which parsing succeeds.
3265+
3266+ > #### Note {: .info }
3267+ >
3268+ > * Since OTP @OTP-20357 @* a binary is accepted; before that only a list.
3269+ >
3270+ > With that change, this function mostly raises an error exception
3271+ > for an argument that is of an invalid type. Before this,
3272+ > common bad arguments were handled and returned ` {error, einval} ` .
30393273""" .
30403274-doc (#{since => <<" OTP R16B" >>}).
30413275-spec parse_strict_address (Address ) ->
0 commit comments