diff --git a/src/Plugin/DataType/IpAddressData.php b/src/Plugin/DataType/IpAddressData.php
new file mode 100644
index 0000000..93e9279
--- /dev/null
+++ b/src/Plugin/DataType/IpAddressData.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Drupal\typed_data\Plugin\DataType;
+
+use Drupal\Core\TypedData\Plugin\DataType\StringData;
+use Drupal\typed_data\TypedData\Type\IpAddressInterface;
+
+/**
+ * The ip_address data type.
+ *
+ * @DataType(
+ *   id = "ip_address",
+ *   label = @Translation("Ip address"),
+ *   constraints = {"Ip" = {"version" = "all"}}
+ * )
+ */
+class IpAddressData extends StringData implements IpAddressInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIp4Address() {
+    if (isset($this->value) && filter_var($this->value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
+      return $this->value;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIp6Address() {
+    if (isset($this->value) && filter_var($this->value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
+      return $this->value;
+    }
+  }
+
+}
diff --git a/src/Plugin/Validation/Constraint/IpConstraint.php b/src/Plugin/Validation/Constraint/IpConstraint.php
new file mode 100644
index 0000000..f765aa7
--- /dev/null
+++ b/src/Plugin/Validation/Constraint/IpConstraint.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Drupal\typed_data\Plugin\Validation\Constraint;
+
+use Symfony\Component\Validator\Constraints\Ip;
+
+/**
+ * IP address constraint.
+ *
+ * @Constraint(
+ *   id = "Ip",
+ *   label = @Translation("Ip", context = "Validation"),
+ *   type = {"ip_address"}
+ * )
+ */
+class IpConstraint extends Ip {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validatedBy() {
+    return '\Symfony\Component\Validator\Constraints\IpValidator';
+  }
+
+}
diff --git a/src/TypedData/Type/IpAddressInterface.php b/src/TypedData/Type/IpAddressInterface.php
new file mode 100644
index 0000000..e814348
--- /dev/null
+++ b/src/TypedData/Type/IpAddressInterface.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Drupal\typed_data\TypedData\Type;
+
+use Drupal\Core\TypedData\Type\StringInterface;
+
+/**
+ * Interface for ip_address data.
+ *
+ * @ingroup typed_data
+ */
+interface IpAddressInterface extends StringInterface {
+
+  /**
+   * Returns the IPv4 address.
+   *
+   * @return string|null
+   *   The IPv4 address or NULL.
+   */
+  public function getIp4Address();
+
+  /**
+   * Returns the IPv6 address.
+   *
+   * @return string|null
+   *   The IPv6 address or NULL.
+   */
+  public function getIp6Address();
+
+}
diff --git a/tests/src/Kernel/IpAddressDataTypeTest.php b/tests/src/Kernel/IpAddressDataTypeTest.php
new file mode 100644
index 0000000..d8ea69e
--- /dev/null
+++ b/tests/src/Kernel/IpAddressDataTypeTest.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace Drupal\Tests\typed_data\Kernel;
+
+use Drupal\Core\TypedData\DataDefinition;
+use Drupal\Core\TypedData\Type\StringInterface;
+use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Tests the functionality of the Ip address datatype.
+ *
+ * @group typed_data
+ */
+class IpAddressDataTypeTest extends KernelTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['system', 'typed_data'];
+
+  /**
+   * Tests that the Ip address data type.
+   */
+  public function testIpAddressDatatype() {
+    $value = $this->randomString();
+    $definition = DataDefinition::create('ip_address');
+    $typed_data = $this->container->get('typed_data_manager')->create($definition, $value, 'ip_address');
+
+    $this->assertTrue($typed_data instanceof TypedDataInterface, 'Typed data object is an instance of the typed data interface.');
+    $this->assertTrue($typed_data instanceof StringInterface, 'Typed data object is an instance of StringInterface).');
+
+    $this->assertTrue($typed_data->getValue() === $value, 'Ip address value was fetched.');
+    $this->assertEquals(1, $typed_data->validate()->count());
+    $new_value = '127.0.0.1';
+    $typed_data->setValue($new_value);
+    $this->assertTrue($typed_data->getValue() === $new_value, 'Ip address value was changed.');
+    $this->assertTrue($typed_data->getIp4Address() === $new_value, 'Ip address is a valid IPv4 address.');
+    $this->assertNull($typed_data->getIp6Address());
+    $this->assertEquals(0, $typed_data->validate()->count());
+
+    $new_value = '::1';
+    $typed_data->setValue($new_value);
+    $this->assertTrue($typed_data->getIp6Address() === $new_value, 'Ip address is a valid IPv6 address.');
+    $this->assertNull($typed_data->getIp4Address());
+    $this->assertEquals(0, $typed_data->validate()->count());
+  }
+
+}
