1+ import { FakerError } from '../../errors/faker-error' ;
12import { ModuleBase } from '../../internal/module-base' ;
23import { charMapping } from './char-mappings' ;
34import * as random_ua from './user-agent' ;
@@ -23,6 +24,82 @@ export type HTTPStatusCodeType =
2324
2425export type HTTPProtocolType = 'http' | 'https' ;
2526
27+ export enum IPv4Network {
28+ /**
29+ * Equivalent to: `0.0.0.0/0`
30+ */
31+ Any = 'any' ,
32+ /**
33+ * Equivalent to: `127.0.0.0/8`
34+ *
35+ * @see [RFC1122](https://www.rfc-editor.org/rfc/rfc1122)
36+ */
37+ Loopback = 'loopback' ,
38+ /**
39+ * Equivalent to: `10.0.0.0/8`
40+ *
41+ * @see [RFC1918](https://www.rfc-editor.org/rfc/rfc1918)
42+ */
43+ PrivateA = 'private-a' ,
44+ /**
45+ * Equivalent to: `172.16.0.0/12`
46+ *
47+ * @see [RFC1918](https://www.rfc-editor.org/rfc/rfc1918)
48+ */
49+ PrivateB = 'private-b' ,
50+ /**
51+ * Equivalent to: `192.168.0.0/16`
52+ *
53+ * @see [RFC1918](https://www.rfc-editor.org/rfc/rfc1918)
54+ */
55+ PrivateC = 'private-c' ,
56+ /**
57+ * Equivalent to: `192.0.2.0/24`
58+ *
59+ * @see [RFC5737](https://www.rfc-editor.org/rfc/rfc5737)
60+ */
61+ TestNet1 = 'test-net-1' ,
62+ /**
63+ * Equivalent to: `198.51.100.0/24`
64+ *
65+ * @see [RFC5737](https://www.rfc-editor.org/rfc/rfc5737)
66+ */
67+ TestNet2 = 'test-net-2' ,
68+ /**
69+ * Equivalent to: `203.0.113.0/24`
70+ *
71+ * @see [RFC5737](https://www.rfc-editor.org/rfc/rfc5737)
72+ */
73+ TestNet3 = 'test-net-3' ,
74+ /**
75+ * Equivalent to: `169.254.0.0/16`
76+ *
77+ * @see [RFC3927](https://www.rfc-editor.org/rfc/rfc3927)
78+ */
79+ LinkLocal = 'link-local' ,
80+ /**
81+ * Equivalent to: `224.0.0.0/4`
82+ *
83+ * @see [RFC5771](https://www.rfc-editor.org/rfc/rfc5771)
84+ */
85+ Multicast = 'multicast' ,
86+ }
87+
88+ export type IPv4NetworkType = `${IPv4Network } `;
89+
90+ const ipv4Networks : Record < IPv4Network , string > = {
91+ [ IPv4Network . Any ] : '0.0.0.0/0' ,
92+ [ IPv4Network . Loopback ] : '127.0.0.0/8' ,
93+ [ IPv4Network . PrivateA ] : '10.0.0.0/8' ,
94+ [ IPv4Network . PrivateB ] : '172.16.0.0/12' ,
95+ [ IPv4Network . PrivateC ] : '192.168.0.0/16' ,
96+ [ IPv4Network . TestNet1 ] : '192.0.2.0/24' ,
97+ [ IPv4Network . TestNet2 ] : '198.51.100.0/24' ,
98+ [ IPv4Network . TestNet3 ] : '203.0.113.0/24' ,
99+ [ IPv4Network . LinkLocal ] : '169.254.0.0/16' ,
100+ [ IPv4Network . Multicast ] : '224.0.0.0/4' ,
101+ } ;
102+
26103/**
27104 * Module to generate internet related entries.
28105 *
@@ -485,15 +562,100 @@ export class InternetModule extends ModuleBase {
485562 /**
486563 * Generates a random IPv4 address.
487564 *
565+ * @param options The optional options object.
566+ * @param options.cidrBlock The optional CIDR block to use. Must be in the format `x.x.x.x/y`. Defaults to `'0.0.0.0/0'`.
567+ *
488568 * @example
489569 * faker.internet.ipv4() // '245.108.222.0'
570+ * faker.internet.ipv4({ cidrBlock: '192.168.0.0/16' }) // '192.168.215.224'
490571 *
491572 * @since 6.1.1
492573 */
493- ipv4 ( ) : string {
494- return Array . from ( { length : 4 } , ( ) => this . faker . number . int ( 255 ) ) . join (
495- '.'
496- ) ;
574+ ipv4 ( options ?: {
575+ /**
576+ * The optional CIDR block to use. Must be in the format `x.x.x.x/y`.
577+ *
578+ * @default '0.0.0.0/0'
579+ */
580+ cidrBlock ?: string ;
581+ } ) : string ;
582+ /**
583+ * Generates a random IPv4 address.
584+ *
585+ * @param options The optional options object.
586+ * @param options.network The optional network to use. This is intended as an alias for well-known `cidrBlock`s. Defaults to `'any'`.
587+ *
588+ * @example
589+ * faker.internet.ipv4() // '245.108.222.0'
590+ * faker.internet.ipv4({ network: 'private-a' }) // '10.199.154.205'
591+ *
592+ * @since 6.1.1
593+ */
594+ ipv4 ( options ?: {
595+ /**
596+ * The optional network to use. This is intended as an alias for well-known `cidrBlock`s.
597+ *
598+ * @default 'any'
599+ */
600+ network ?: IPv4NetworkType ;
601+ } ) : string ;
602+ /**
603+ * Generates a random IPv4 address.
604+ *
605+ * @param options The optional options object.
606+ * @param options.cidrBlock The optional CIDR block to use. Must be in the format `x.x.x.x/y`. Defaults to `'0.0.0.0/0'`.
607+ * @param options.network The optional network to use. This is intended as an alias for well-known `cidrBlock`s. Defaults to `'any'`.
608+ *
609+ * @example
610+ * faker.internet.ipv4() // '245.108.222.0'
611+ * faker.internet.ipv4({ cidrBlock: '192.168.0.0/16' }) // '192.168.215.224'
612+ * faker.internet.ipv4({ network: 'private-a' }) // '10.199.154.205'
613+ *
614+ * @since 6.1.1
615+ */
616+ ipv4 (
617+ options ?:
618+ | {
619+ /**
620+ * The optional CIDR block to use. Must be in the format `x.x.x.x/y`.
621+ *
622+ * @default '0.0.0.0/0'
623+ */
624+ cidrBlock ?: string ;
625+ }
626+ | {
627+ /**
628+ * The optional network to use. This is intended as an alias for well-known `cidrBlock`s.
629+ *
630+ * @default 'any'
631+ */
632+ network ?: IPv4NetworkType ;
633+ }
634+ ) : string ;
635+ ipv4 (
636+ options : { cidrBlock ?: string ; network ?: IPv4NetworkType } = { }
637+ ) : string {
638+ const { network = 'any' , cidrBlock = ipv4Networks [ network ] } = options ;
639+
640+ if ( ! / ^ \d { 1 , 3 } \. \d { 1 , 3 } \. \d { 1 , 3 } \. \d { 1 , 3 } \/ \d { 1 , 2 } $ / . test ( cidrBlock ) ) {
641+ throw new FakerError (
642+ `Invalid CIDR block provided: ${ cidrBlock } . Must be in the format x.x.x.x/y.`
643+ ) ;
644+ }
645+
646+ const [ ipText , subnet ] = cidrBlock . split ( '/' ) ;
647+ const subnetMask = 0xffffffff >>> Number . parseInt ( subnet ) ;
648+ const [ rawIp1 , rawIp2 , rawIp3 , rawIp4 ] = ipText . split ( '.' ) . map ( Number ) ;
649+ const rawIp = ( rawIp1 << 24 ) | ( rawIp2 << 16 ) | ( rawIp3 << 8 ) | rawIp4 ;
650+ const networkIp = rawIp & ~ subnetMask ;
651+ const hostOffset = this . faker . number . int ( subnetMask ) ;
652+ const ip = networkIp | hostOffset ;
653+ return [
654+ ( ip >>> 24 ) & 0xff ,
655+ ( ip >>> 16 ) & 0xff ,
656+ ( ip >>> 8 ) & 0xff ,
657+ ip & 0xff ,
658+ ] . join ( '.' ) ;
497659 }
498660
499661 /**
0 commit comments