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();