Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions app/Exceptions/Utils/Whois/WhoisException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

/*
* Copyright (C) 2009 - 2026 Internet Neutral Exchange Association Company Limited By Guarantee.
* All Rights Reserved.
*
* This file is part of IXP Manager.
*
* IXP Manager is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version v2.0 of the License.
*
* IXP Manager is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GpNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License v2.0
* along with IXP Manager. If not, see:
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/

namespace IXP\Exceptions\Utils\Whois;

final class WhoisException extends \Exception {}
27 changes: 16 additions & 11 deletions app/Http/Controllers/Api/V4/WhoisController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace IXP\Http\Controllers\Api\V4;

/*
* Copyright (C) 2009 - 2021 Internet Neutral Exchange Association Company Limited By Guarantee.
* Copyright (C) 2009 - 2026 Internet Neutral Exchange Association Company Limited By Guarantee.
* All Rights Reserved.
*
* This file is part of IXP Manager.
Expand All @@ -28,7 +28,10 @@
use IXP\Services\PeeringDb;
use Illuminate\Http\{Request,Response};

use IXP\Utils\Whois;
use IXP\Utils\Whois\{
Whois,
WhoisHost,
};

/**
* WhoisController
Expand All @@ -45,14 +48,16 @@ class WhoisController extends Controller
/**
* API call to do a Whois looking on an AS number
*
* @param PeeringDb $pdb service to resolve via PeeringDb
* @param Whois $whois A Whois instance
* @param Request $r
* @param string $asn The AS number
* @param string $asn The AS number
*
* @return Response
*/
public function asn( PeeringDb $pdb, Request $r, string $asn ): Response
public function asn( PeeringDb $pdb, #[WhoisHost('asn2')] Whois $whois, Request $r, string $asn ): Response
{
$response = Cache::remember( 'api-v4-whois-asn-' . $asn, config('ixp_api.whois.cache_ttl'), function () use ( $pdb, $asn ) {
$response = Cache::remember( 'api-v4-whois-asn-' . $asn, config('ixp_api.whois.cache_ttl'), function () use ( $pdb, $whois, $asn ): string {

// try PeeringDB first
if( $net = $pdb->getNetworkByAsn( $asn ) ) {
Expand All @@ -65,7 +70,6 @@ public function asn( PeeringDb $pdb, Request $r, string $asn ): Response
$response = "Querying PeeringDB failed:\n\nError:{$pdb->error}\n\nTrying " . config( 'ixp_api.whois.asn2.host' ) . ":\n\n";
}

$whois = new Whois( config( 'ixp_api.whois.asn2.host' ), config( 'ixp_api.whois.asn2.port' ) );
$response .= $whois->whois( 'AS' . (int)$asn );

return $response;
Expand All @@ -77,17 +81,18 @@ public function asn( PeeringDb $pdb, Request $r, string $asn ): Response
/**
* API call to do a Whois looking on a prefix
*
* @param Whois $whois A whois instance
* @param string $prefix The IP address element of the prefix
* @param string|null $mask The mask length
*
* @return Response
*/
public function prefix( string $prefix, string $mask = null ): Response
public function prefix( #[WhoisHost('prefix')] Whois $whois, string $prefix, ?string $mask = null ): Response
{
$response = Cache::remember( 'api-v4-whois-prefix-' . $prefix . '-' . $mask, config('ixp_api.whois.cache_ttl'), function () use ( $prefix, $mask ) {
$whois = new Whois( config('ixp_api.whois.prefix.host'), config('ixp_api.whois.prefix.port') );
return $whois->whois( $prefix .'/' . $mask );
});
// Don't append slash unless we're sending the mask also
$response = Cache::remember( 'api-v4-whois-prefix-' . $prefix . '-' . $mask, config('ixp_api.whois.cache_ttl'),
fn() => $whois->whois( $prefix . ($mask ? "/$mask" : ""))
);

return response( $response, 200 )->header('Content-Type', 'text/plain');
}
Expand Down
15 changes: 5 additions & 10 deletions app/Utils/Whois.php → app/Utils/Whois/Whois.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?php

namespace IXP\Utils;
namespace IXP\Utils\Whois;

/*
* Copyright (C) 2009 - 2020 Internet Neutral Exchange Association Company Limited By Guarantee.
* Copyright (C) 2009 - 2026 Internet Neutral Exchange Association Company Limited By Guarantee.
* All Rights Reserved.
*
* This file is part of IXP Manager.
Expand All @@ -28,19 +28,19 @@
*
* A Whois implementation
*
* @package IXP\Utils
* @package \IXP\Utils\Whois
*/
class Whois
{
/**
* @var string Whois server hostname
*/
private $host;
private string $host;

/**
* @var int Whois server port
*/
private $port;
private int $port;


/**
Expand All @@ -54,11 +54,6 @@ public function __construct( string $host, int $port )
$this->port = $port;
}


/**
*
*/

/**
* Do a whois lookup
*
Expand Down
60 changes: 60 additions & 0 deletions app/Utils/Whois/WhoisHost.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

/*
* Copyright (C) 2009 - 2026 Internet Neutral Exchange Association Company Limited By Guarantee.
* All Rights Reserved.
*
* This file is part of IXP Manager.
*
* IXP Manager is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version v2.0 of the License.
*
* IXP Manager is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License v2.0
* along with IXP Manager. If not, see:
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/

declare(strict_types=1);

namespace IXP\Utils\Whois;

use Attribute;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Container\ContextualAttribute;

/**
* Attribute containing a whois server configuration name, allowing specific Whois server
* to be resolved from configuration.
*
* @author Thomas Kerin <thomas@islandbridgenetworks.ie>
* @category Whois
* @package IXP\Utils\Whois
* @copyright Copyright (C) 2009 - 2026 Internet Neutral Exchange Association Company Limited By Guarantee
* @license http://www.gnu.org/licenses/gpl-2.0.html GNU GPL V2.0
*/
#[Attribute(Attribute::TARGET_PARAMETER)]
readonly class WhoisHost implements ContextualAttribute
{
/**
* @param string $name The name of the whois config to load
*/
public function __construct(public string $name) {}

/**
* @param WhoisHost $attribute containing whois config name
* @param Container $container for dependency injection
* @return Whois
* @throws \IXP\Exceptions\Utils\Whois\WhoisException
*/
public static function resolve(self $attribute, Container $container): Whois
{
return $container->make(WhoisResolver::class)->get($attribute->name);
}
}
53 changes: 53 additions & 0 deletions app/Utils/Whois/WhoisResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/*
* Copyright (C) 2009 - 2026 Internet Neutral Exchange Association Company Limited By Guarantee.
* All Rights Reserved.
*
* This file is part of IXP Manager.
*
* IXP Manager is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version v2.0 of the License.
*
* IXP Manager is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License v2.0
* along with IXP Manager. If not, see:
*
* http://www.gnu.org/licenses/gpl-2.0.html
*/

declare(strict_types=1);

namespace IXP\Utils\Whois;

use IXP\Exceptions\Utils\Whois\WhoisException;

/**
* Resolver class for whois servers.
* Allows loading different WHOIS hosts from configuration files.
*
* @package IXP\Services\Whois
*/
class WhoisResolver
{
/**
* Given a provided server, this function loads the host/port from configuration and returns a Whois instance.
*
* @param string $server
* @return Whois
* @throws WhoisException
*/
public function get( string $server ): Whois
{
if ( !( config()->has("ixp_api.whois.{$server}.host") && config()->has("ixp_api.whois.{$server}.port") ) ) {
throw new WhoisException( "Configuration not found for whois server '$server'" );
}

return new Whois( config( "ixp_api.whois.{$server}.host" ), (int) config( "ixp_api.whois.{$server}.port" ) );
}
}
1 change: 1 addition & 0 deletions data/ci/known-good/peeringdb/getnetwork.inex.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"data": [{"id": 502, "org_id": 679, "name": "INEX Route Collectors", "aka": "Internet Neutral Exchange Association Ltd", "name_long": "", "website": "http://www.inex.ie/", "social_media": [{"service": "website", "identifier": "http://www.inex.ie/"}], "asn": 2128, "looking_glass": "http://www.inex.ie/lg/", "route_server": "", "irr_as_set": "", "info_type": "Route Collector", "info_types": ["Route Collector"], "info_prefixes4": 0, "info_prefixes6": 0, "info_traffic": "", "info_ratio": "Balanced", "info_scope": "Regional", "info_unicast": true, "info_multicast": false, "info_ipv6": true, "info_never_via_route_servers": false, "ix_count": 2, "fac_count": 0, "notes": "INEX is an IXP in Dublin, Ireland.", "netixlan_updated": "2026-03-26T17:18:39Z", "netfac_updated": null, "poc_updated": "2025-10-13T09:07:32Z", "policy_url": "", "policy_general": "Open", "policy_locations": "Not Required", "policy_ratio": false, "policy_contracts": "Not Required", "netfac_set": [], "netixlan_set": [{"id": 1782, "ix_id": 48, "name": "INEX LAN1: INEX LAN1", "ixlan_id": 48, "notes": "", "speed": 1000, "asn": 2128, "ipaddr4": "185.6.36.126", "ipaddr6": "2001:7f8:18::f:0:1", "is_rs_peer": true, "bfd_support": false, "operational": true, "net_side_id": null, "ix_side_id": null, "created": "2010-07-29T00:00:00Z", "updated": "2024-05-28T10:07:37Z", "status": "ok"}, {"id": 34373, "ix_id": 1262, "name": "INEX Cork: Peering LAN", "ixlan_id": 1262, "notes": "", "speed": 1000, "asn": 2128, "ipaddr4": "185.1.69.126", "ipaddr6": "2001:7f8:18:210::126", "is_rs_peer": true, "bfd_support": false, "operational": true, "net_side_id": null, "ix_side_id": 620, "created": "2017-04-26T18:30:19Z", "updated": "2026-03-26T17:18:39Z", "status": "ok"}], "poc_set": [{"id": 1547, "role": "NOC", "visible": "Public", "name": "INEX Operations", "phone": "+35315313339", "email": "operations@inex.ie", "url": "", "created": "2010-07-29T00:00:00Z", "updated": "2025-10-13T09:07:32Z", "status": "ok"}], "allow_ixp_update": false, "status_dashboard": "", "rir_status": "ok", "rir_status_updated": "2024-06-26T04:47:55Z", "logo": "https://peeringdb-media-prod.s3.amazonaws.com/media/logos_user_supplied/network-502-9a7956f5.png", "created": "2005-06-07T21:13:52Z", "updated": "2025-10-13T09:05:37Z", "status": "ok"}], "meta": {}}
16 changes: 16 additions & 0 deletions data/ci/known-good/peeringdb/netAsAscii.inex.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
PeeringDB Network Details of AS2128
==================================================

Name: INEX Route Collectors
Internet Neutral Exchange Association Ltd

Website: http://www.inex.ie/

Peering Policy: Open

Notes:



==================================================

11 changes: 11 additions & 0 deletions data/ci/known-good/whois-prefix.8.8.8.8.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
route: 8.8.8.0/24
origin: AS15169
descr: Google
notify: radb-contact@google.com
mnt-by: MAINT-AS15169
changed: radb-contact@google.com 20230208
source: RADB
last-modified: 2023-11-13T16:14:55Z
rpki-ov-state: valid


5 changes: 5 additions & 0 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2416,6 +2416,11 @@
<code><![CDATA[public static function toArpa( string $ip, int $protocol ): string]]></code>
</MissingDocblockType>
</file>
<file src="app/Utils/Whois/WhoisResolver.php">
<InvalidCast>
<code><![CDATA[config( "ixp_api.whois.{$server}.port" )]]></code>
</InvalidCast>
</file>
<file src="data/SocialiteProviders/src/PeeringDB/Provider.php">
<ImplicitToStringCast>
<code><![CDATA[$response->getBody()]]></code>
Expand Down
Loading
Loading