NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name BGP.HE.net - Improved
// @namespace BGP_HE_net
// @description BGP.HE.net - Fills Empty IRR tabs by using data from RADB, Keep browser validation cookie, postpone validation for new sessions. Add onclick links to all country flags for easier browsing experience.
// @include http://bgp.he.net/*
// @include https://bgp.he.net/*
// @version 3.0
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @grant GM_log
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.0.4/js.cookie.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery-searcher/0.3.0/jquery.searcher.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/df-number-format/2.1.6/jquery.number.min.js
// @author Volkan K.
// @license MIT
// @run-at document-end
// @connect irr.bboi.net
// @connect bgp.he.net
// @connect peeringdb.com
// @connect ip-api.com
// ==/UserScript==
this.$ = this.jQuery = jQuery.noConflict(true);
if(typeof GM_addStyle === "undefined") {
function GM_addStyle(/* String */ styles) {
var oStyle = document.createElement("style");
oStyle.setAttribute("type", "text\/css");
oStyle.appendChild(document.createTextNode(styles));
var head = document.getElementsByTagName('head')[0];
if (!head) { // no head yet, stick it whereever
document.documentElement.appendChild(oStyle);
} else {
head.appendChild(oStyle);
}
}
}
if(typeof GM_log === "undefined") {
function GM_log(log) {
if(console)
console.log(log);
else
alert(log);
}
}
var debug_internal = 1; // 1=enable debug , 0 =disable debug
function debugLog(message, do_alert) {
if (debug_internal==1) {
console.log("USER-SCRIPT BGP_HE_NET | " + message);
}
if (do_alert && typeof alert === "function") {
alert("USER-SCRIPT BGP_HE_NET | " + message);
}
}
// Browser Validation no-more
current_c_val = Cookies.get('c');
consistent_c = Cookies.set('c', current_c_val, { expires: 365 });
// Empty IRR tab fix
function append_irr_source(title,id) {
var html_header="<div class='irrbox'><div class='irrsource'>"+title+"</div><span class='irrdata' id='"+id+"'>";
var html_footer="</span><div class='clear'></div></div>";
$("div#irr").append(html_header+html_footer);
}
function add_links_to_result(result) {
result = result.replace(/([ \t]+)AS-([\w-]+)/ig, '$1<a href="/irr/as-set/AS-$2" title="AS-$2">AS-$2</a>'); // Add links for AS-SETs.
result = result.replace(/([ \t]+)RS-([\w-]+)/ig, '$1<a href="/irr/route-set/RS-$2" title="RS-$2">RS-$2</a>'); // Add links for ROUTE-SETs.
result = result.replace(/([ \t]+)AS(\d+)/ig, '$1<a href="/AS$2" title="AS$2">AS$2</a>'); // Add links for ASNs.
result = result.replace(/\b((?:[0-9]{1,3}\.){3}[0-9]{1,3})\b/g, '<a href="/ip/$1" title="$1">$1</a>'); // Add links for IPv4 addresses (simple regex)
return result;
}
function convert_pdb_arr_to_str (result_arr){
result = "";
for (x in result_arr) {
switch(x){
case "id":
key = "Network ID";
break;
case "org_id":
key = "Organization ID";
break;
case "name":
key = "Organization Name";
break;
case "aka":
key = "Also Known As";
break;
case "website":
key = "Company Website";
break;
case "asn":
key = "Primary ASN";
break;
case "looking_glass":
key = "Looking Glass URL";
break;
case "route_server":
key = "Route Server URL";
break;
case "irr_as_set":
key = "IRR Record AS Set";
break;
case "info_type":
key = "Network Type";
break;
case "info_prefixes4":
key = "IPv4 Prefixes";
break;
case "info_prefixes6":
key = "IPv6 Prefixes";
break;
case "info_traffic":
key = "Traffic Levels";
break;
case "info_ratio":
key = "Traffic Ratios";
break;
case "info_scope":
key = "Geographic Scope";
break;
case "info_unicast":
key = "Unicast Support";
break;
case "info_multicast":
key = "Multicast Support";
break;
case "info_ipv6":
key = "IPv6 Support";
break;
case "notes":
key = "Notes";
break;
case "policy_url":
key = "Peering Policy URL";
break;
case "policy_general":
key = "General Policy";
break;
case "policy_locations":
key = "Multiple Locations Policy";
break;
case "policy_ratio":
key = "Ratio Requirement Policy";
break;
case "policy_contracts":
key = "Contract Requirement Policy";
break;
case "created":
key = "Record Created";
break;
case "updated":
key = "Record Updated";
break;
case "status":
key = "Record Status";
break;
default:
key = x;
}
result += key+" : " + result_arr[x] + "<br />";
}
return result;
}
var myregexp = /AS(\d+)/i;
var match = myregexp.exec(window.location.pathname);
if (match != null) {
current_as = match[1];
} else {
current_as = "";
}
var is_ixp_report = false;
var ixp_report_regexp = /report\/exchanges/i;
var ixp_report_match = ixp_report_regexp.exec(window.location.pathname);
if (ixp_report_match != null) {
is_ixp_report=true;
//console.log("we should be on IXP report page."); // for debug, comment on production
}
if (is_ixp_report==true) {
var ixp_count=$("table#exchangestable > tbody > tr").length;
//console.log("ixp_count="+ixp_count); // for debug, comment on production
$("table#exchangestable > thead > tr > th:first").append(" ("+ixp_count+")");
}
if (($("div#irr").children().size() < 1 || $("div.irrsource:contains('RADB')").length<1)&& current_as != "") {
// no siblings , BGP tool does not have IRR info to display. do your job..
// Note: you can use AS38861 and AS24482 for testing, these currently dont have IRR record on HE.net BGP tool.
append_irr_source('RADB', 'radb_place_elem');
GM_xmlhttpRequest({
method: "GET",
url: "http://irr.bboi.net/cgi-bin/whois.php?value=AS"+current_as+"&submit=WhoIS",
onerror: function(oEvent){ alert("Error " + oEvent.target.status + " occurred while receiving the document."); },
onload: function(response){
if (response.readyState !== 4 || response.status !== 200) return;
var response_parsed=$.parseHTML(response.responseText);
var whois_data = $('pre:contains("whois.radb.net")', response_parsed);
//alert(whois_data); alert(whois_data.length); // for debug
if (whois_data.length != 0) {
result = whois_data.html();
/*
result ="[Querying whois.radb.net]"+"\n"
+"[whois.radb.net]"+"\n"
+"aut-num: AS24482"+"\n"
+"as-name: SGGS-AS-AP"+"\n"
+"descr: SG.GS"+"\n"
+"country: SG"+"\n"
+"admin-c: HC755-AP"+"\n"
+"tech-c: HC755-AP"+"\n"
+"mnt-by: MAINT-SG-SGGS"+"\n"
+"changed: admin@sg.gs 20140128"+"\n"
+"mnt-irt: IRT-SGGS-SG"+"\n"
+"import: from AS6777 accept ANY"+"\n"
+"import: from AS8631 accept AS-MSKROUTESERVER"+"\n"
+"import: from AS61955 accept AS-COLOCATIONIX"+"\n"
+"export: to AS6777 action community .= { 6777:6777, 6777:855, 6777:4651, 6777:4761, 6777:6327, 6777:6939, 6777:8529, 6777:9304, 6777:9318, 6777:9329, 6777:9498, 6777:9505, 6777:10026, 6777:20080, 6777:38082, 6777:16276, 6777:45629, 6777:46786 }; announce AS-SGGS"+"\n"
+"export: to AS8631 announce AS-SGGS"+"\n"
+"export: to AS61955 announce AS-SGGS"+"\n"
+"source: APNIC"; // for testing and debugging.
*/
result = add_links_to_result(result);
} else {
// no match, error
result = "I couldn't find RADB record :(";
}
$("span#radb_place_elem").append(result);
/*if( $("div#irr").is(":visible") ){ // this is not necessary. for testing-only.
$("div#irr").hide();
$("div#irr").show();
}*/
}
});
}
if (($("div#irr").children().size() < 1 || $("div.irrsource:contains('PeeringDB')").length<1)&& current_as != "") {
// no siblings , BGP tool does not have IRR info to display. do your job..
// Note: you can use AS38861 and AS24482 for testing, these currently dont have IRR record on HE.net BGP tool.
append_irr_source('PeeringDB', 'pdb_place_elem');
GM_xmlhttpRequest({
method: "GET",
url: "https://www.peeringdb.com/api/net?depth=0&asn="+current_as,
onerror: function(oEvent){
$("span#pdb_place_elem").append("Error " + oEvent.target.status + " occurred while receiving the PeeringDB record.");
return;
},
onload: function(response){
if (response.readyState !== 4 || response.status !== 200){
$("span#pdb_place_elem").append(response.statusText);
return;
}
// we can parse now
myObj = JSON.parse(response.responseText);
if (myObj["data"].length>0) {
result_arr = myObj["data"][0];
//console.log(result_arr); // for debugging
result = convert_pdb_arr_to_str(result_arr);
result = add_links_to_result(result);
} else {
// no match, error
result = "I couldn't find PeeringDB record :(";
}
$("span#pdb_place_elem").append(result);
/*if( $("div#irr").is(":visible") ){ // this is not necessary. for testing-only.
$("div#irr").hide();
$("div#irr").show();
}*/
}
});
}
function fetch_peeringdb_link(current_as) {
GM_xmlhttpRequest({
method: "HEAD",
url: 'https://www.peeringdb.com/asn/'+current_as,
onerror: function(oEvent){
debugLog("Error " + oEvent.status + " occurred while receiving the document.");
prepend_peeringdb_link(current_as,"Error " + oEvent.status);
},
onload: function(response){
if (response.readyState !== 4 || response.status !== 200) {
debugLog("ERROR: Response status is not OK (200) but "+response.status);
if (response.status==404){
prepend_peeringdb_link(current_as,"N/A");
} else {
prepend_peeringdb_link(current_as,"Server Error");
}
} else {
// show result
if (response.statusText=="") {
prepend_peeringdb_link(current_as,"OK");
} else {
prepend_peeringdb_link(current_as,response.statusText);
}
}
// console.log(response); // for debug only.
debugLog("PeeringDB response.statusText = "+ response.statusText);
}
});
}
function prepend_peeringdb_link(current_as,responseText){
peeringdb_html='<div class="asleft" id="peeringdb">PeeringDB Page:</div>'+"\n"
+'<div class="asright"><a target="_blank" href="https://www.peeringdb.com/asn/'+current_as+'">https://peeringdb.com/asn/'+current_as+'</a>';
if (responseText!=null && responseText != "") {
peeringdb_html+=' ('+responseText+')';
}
peeringdb_html+='</div>';
$( "div.asinfotext" ).prepend(peeringdb_html);
}
// Add PeeringDB.com link
if ($("div#peeringdb").size() < 1 && current_as != "") {
// good to go.
fetch_peeringdb_link(current_as);
}
function search_text_node(my_selector,my_text) {
return $(my_selector)
.contents()
.filter(function(){
return this.nodeType === 3;
})
.filter(function(){
// Only match when contains 'simple string' anywhere in the text
return this.nodeValue.indexOf(my_text) != -1;
});
}
// Add v4-only and v6-only counts
if ($("div#v4-v6-only").size() < 1 && current_as != "") {
// good to go.
bgp_all = search_text_node('div.asleft', "BGP Peers Observed (all):").eq(-1).text().replace(/[\s,.]/g, '').split(":")[1];
bgp_v4 = search_text_node('div.asleft', "BGP Peers Observed (v4):").eq(-1).text().replace(/[\s,.]/g, '').split(":")[1];
bgp_v6 = search_text_node('div.asleft', "BGP Peers Observed (v6):").eq(-1).text().replace(/[\s,.]/g, '').split(":")[1];
debugLog("bgp_all = "+bgp_all+" , bgp_v4 = "+bgp_v4+" , bgp_v6 = "+bgp_v6); // for debug only.
if ( $.isNumeric(bgp_all) && $.isNumeric(bgp_v4) && $.isNumeric(bgp_v6) ) {
// we got values now we calculate and print v4-only and v6-only
bgp_v4_only = parseInt(bgp_all)-parseInt(bgp_v6);
bgp_v6_only = parseInt(bgp_all)-parseInt(bgp_v4);
bgp_dual_stack = parseInt(bgp_all)-parseInt(bgp_v4_only)-parseInt(bgp_v6_only);
debugLog("bgp_v4_only = "+bgp_v4_only+" , bgp_v6_only = "+bgp_v6_only+" , bgp_dual_stack = "+bgp_dual_stack); // for debug only.
div_v4_v6_only_html = "<div id='v4-v6-only'><hr />BGP Peers Observed (v4-only): "+$.number( bgp_v4_only,0,'.',',' )+"<br />BGP Peers Observed (v6-only): "+$.number( bgp_v6_only,0,'.',',' )+"<br />BGP Peers Observed (DualStack): "+$.number( bgp_dual_stack,0,'.',',' )+"</div>";
search_text_node('div.asleft', "BGP Peers Observed (v6):").eq(-1).after(div_v4_v6_only_html);
}
}
var myregexp2 = /country\/(\w+)/i;
var match2 = myregexp2.exec(window.location.pathname);
if (match2 != null) {
current_cc = match2[1];
} else {
current_cc = "";
}
if (current_cc != "") {
// country reports need to be improved
$( "ul.tabmenu" ).append('<li id="tab_exchanges" class="tabmenuli">Internet Exchanges</li>');
$( "div#content" ).append('<div id="exchanges" class="tabdata hidden"></div>');
GM_xmlhttpRequest({
method: "GET",
url: location.protocol+"//bgp.he.net/report/exchanges",
onerror: function(oEvent){ alert("Error " + oEvent.target.status + " occurred while receiving the document."); },
onload: function(response){
/*alert("response.status="+response.status
+";response.readyState="+response.readyState
+";response.responseText="+response.responseText); // for debug*/
if (response.readyState !== 4 || response.status !== 200) return;
// we can parse now
var response_parsed=$.parseHTML(response.responseText);
var exchanges_table = $('table#exchangestable', response_parsed);
//alert(exchanges_table); alert(exchanges_table.length); // for debug
if (exchanges_table.length != 0) {
result = exchanges_table.get(0);
} else {
// no match, error
result = "I couldn't find Internet Exchange records for country :(";
}
$("div#exchanges").append(result);
$("div#exchanges table tbody tr").each(function() {
if ($( this ).find("td:nth-child(4):contains('"+current_cc+"')").length<1 ) {
$( this ).remove(); // wrong country code, remove!
}
});
$("div#exchanges table").css('width', '100%');
if ( document.location.hash ) {
hash=document.location.hash.substring(1);
$('.tabmenuselected').removeClass('tabmenuselected');
$('.tabdata').addClass('hidden');
$('#tab' + hash).addClass('tabmenuselected');
$('#' + hash.substring(1)).removeClass('hidden');
}
sortables_init();
run_tables_searcher();
}
});
}
// Use click events for faster load, as it wont alter page code unless you click.
//$('div.flag > img[src*="/flags/"]').click(add_country_report_links);
// Use mouseenter events for fastest browsing, as it wont alter page code unless the mouse enters flag element and prompt is not used.
$('div.flag > img[src*="/flags/"]').mouseenter(add_country_report_links);
GM_addStyle("div.flag > img {cursor: pointer; cursor: hand;}");
$("ul.tabmenu li.tabmenuli").each(function() {
//alert( $(this).attr('id').substring(3) );
$(this).wrapInner('<a href="#'+$(this).attr('id').substring(3)+'" style="text-decoration:none;"></a>');
});
function add_country_report_links (event) {
//alert ("debug1");
var myregexp = /\/flags\/([\w]{2})\.gif/i;
var match = myregexp.exec($( this ).attr('src'));
if (match != null) {
//alert ("debug2");
var country_code = match[1].toUpperCase();
if (/^mouse/i.test(event.type)){ // this should be mouse event, so we do wrap.
$( this ).wrap("<a href='/country/" + country_code + "'>");
$( this ).off("mouseenter mouseleave mousedown mouseup mouseover mouseout mousemove");
} else { // this should be click() call, so we do redirect.
var r= confirm ("Do you want to be redirected to country report for "+$( this ).attr('alt')+" ("+country_code+") ?")
if (r == true) {
window.location.href = "/country/"+country_code;
} else {
$( this ).wrap("<a href='/country/" + country_code + "'>");
$( this ).off("click");
}
}
return true;
} else {
//alert ("debug3");
var country_code = "";
return false;
}
}
function run_tables_searcher () {
$("table.sortable, div#search > table").each(function( index, element ) {
//console.log( $( this ).text() ); // for debug.
if($(this).is('[class*="mysearchtable"]')) {
return ;
}
$( this ).before('<label>Search for: <input id="mysearchinput'+index+'" type="text"></label>');
$( this ).addClass('mysearchtable'+index);
$(this).searcher({
itemSelector: "tbody > tr",
textSelector: "td",
inputSelector: "#mysearchinput"+index,
toggle: function(item, containsText) {
// use a typically jQuery effect instead of simply showing/hiding the item element
if (containsText)
$(item).fadeIn();
else
$(item).fadeOut();
}
});
});
}
run_tables_searcher();
function add_ipv4_to_home () {
GM_xmlhttpRequest({
method: "GET",
url: 'http://ip-api.com/json',
onerror: function(oEvent){ alert("Error " + oEvent.target.status + " occurred while receiving the document."); },
onload: function(response){
/*alert("response.status="+response.status
+";response.readyState="+response.readyState
+";response.responseText="+response.responseText); // for debug*/
if (response.readyState !== 4 || response.status !== 200) return;
// we can parse now
var data=JSON.parse(response.responseText);
//console.log(JSON.stringify(data, null, 2)); //for debugging
var asn=data.as.split(" ")[0];
var isp=data.org;
var ipa=data.query;
var cc=data.countryCode.toLowerCase();
var cc_uc=data.countryCode.toUpperCase();
var cn=data.country;
$("div#welcome").append('<p> </p><div>\
Your IPv4 address is <a href="/ip/'+ipa+'" class="boldlink">'+ipa+'</a><br>Announced By <a href="/'+asn+'" class="boldlink">'+asn+'</a> ('+isp+')\
<div class="flag alignright floatright"><a href="https://bgp.he.net/country/'+cc_uc+'"><img alt="'+cn+'" src="/images/flags/'+cc+'.gif" title="'+cn+'"></a></div>\
</div>');
}
});
}
add_ipv4_to_home();