For reference, because I have a mental block about remembering this:
netsh interface ipv4 set dnsservers "Local Area Connection" static 8.8.8.8 primary
netsh interface ipv4 set address "Local Area Connection" static 1.1.1.2 255.255.255.0 1.1.1.1
netsh interface ipv4 set address "Local Area Connection" source=dhcp
Friday, March 30, 2012
Friday, March 9, 2012
Collection of vim Tips
Just a collection of vim tips & tricks for future reference.
Best of vim Tips
vim | Arabesque
vim Graphical Cheat Sheet
Why Do Those Nutheads Use vi?
vim cheatsheet
vim revisited
Python and vim
Best of vim Tips
vim | Arabesque
vim Graphical Cheat Sheet
Why Do Those Nutheads Use vi?
vim cheatsheet
vim revisited
Python and vim
Wednesday, March 7, 2012
PyLab with iPython on MacOS X 64-bit
Putting this here for search engine fodder, since it took me a while to figure out...
If you try to run the way-cool PyLab feature of iPython on MacOS X with a 64-bit platform (e.g., my iMac running Lion), you get this:
ImportError: dlopen(/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/numpy/core/multiarray.so, 2): no suitable image found. Did find:
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/numpy/core/multiarray.so: no matching architecture in universal wrapper
What this rather cryptic error means is that the library is 32-bit. To get it to work simply run it with the "arch -i386" command:
The numpy module should now load normally, and PyLab should start.
If you try to run the way-cool PyLab feature of iPython on MacOS X with a 64-bit platform (e.g., my iMac running Lion), you get this:
ImportError: dlopen(/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/numpy/core/multiarray.so, 2): no suitable image found. Did find:
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/numpy/core/multiarray.so: no matching architecture in universal wrapper
What this rather cryptic error means is that the library is 32-bit. To get it to work simply run it with the "arch -i386" command:
$ arch -i386 ipython --pylab
The numpy module should now load normally, and PyLab should start.
Friday, February 10, 2012
Cisco CDR Timestamp and IP Address Conversion
The call detail records (CDRs) used by Cisco Unified Communications Manager (aka Call Manager) can be tricky to interpret. Two fields that are frequently confusing are the IP address fields and the timestamp field.
Continuing my theme of using Python to help with Cisco product administration, here's how to convert timestamps and IP addresses to human-readable format.
Timestamps are pretty easy. They're recorded in UNIX epoch time and there are lots of examples available showing how to convert them using Excel or various scripting tools. In Python:
It took me a while to figure out how to convert IPv4 addresses, since CUCM uses signed 32-bit integers to represent IP addresses and Python's long integers can be of infinite length. First, a review of how to do the conversion manually is in order. Let's say that a CUCM CDR lists an IP address as "-2126438902". First, we convert this signed 32-bit integer to hex using Windows calculator:
Next, we break the hex number into 1-byte chunks, and reverse the order:
Finally, we convert each byte to decimal and put them together into an IP address:
Here's the Python function to do the conversion:
And here it is in the interpreter showing that it works for reasonable input types:
I don't have access to an IPv6-aware CUCM install, so you're on your own for that!
Continuing my theme of using Python to help with Cisco product administration, here's how to convert timestamps and IP addresses to human-readable format.
Timestamps are pretty easy. They're recorded in UNIX epoch time and there are lots of examples available showing how to convert them using Excel or various scripting tools. In Python:
import time
def time_to_string(time_value):
"""convert Unix epoch time to a human readable string"""
return time.strftime("%m/%d/%Y %H:%M:%S",time.localtime(float(time_value)))
It took me a while to figure out how to convert IPv4 addresses, since CUCM uses signed 32-bit integers to represent IP addresses and Python's long integers can be of infinite length. First, a review of how to do the conversion manually is in order. Let's say that a CUCM CDR lists an IP address as "-2126438902". First, we convert this signed 32-bit integer to hex using Windows calculator:
-2126438902 = 0x81411E0A
Next, we break the hex number into 1-byte chunks, and reverse the order:
0x0A
0x1E
0x41
0x81
Finally, we convert each byte to decimal and put them together into an IP address:
10.30.65.129
Here's the Python function to do the conversion:
And here it is in the interpreter showing that it works for reasonable input types:
>>> int_to_ip('-2126438902')
'10.30.65.129'
>>> int_to_ip(-2126438902)
'10.30.65.129'
>>> int_to_ip(-2126438902L)
'10.30.65.129'
I don't have access to an IPv6-aware CUCM install, so you're on your own for that!
Sunday, January 29, 2012
Amusement: Python and Netmasks
As a network engineer, it's not uncommon for me to need to convert between hex and decimal. While I'm reasonably good at doing this in my head for smaller numbers, when it comes to deciphering stuff like higher TCP or UDP port numbers written in hex, I usually end up using the Python interpreter that's usually open somewhere on my machine. For me, the Python interpreter is the best general purpose calculator app I've found. Using the port number for Flash as an example:
The topic of numeric base conversions often makes my mind drift to every former networking instructor's pet topics, IPv4 subnetting. The other day, I started playing with using the Python interpreter to find network IDs, which is really easy as long as you're using hex:
This little snippet finds the bitwise-AND of 10.10.10.37 and 255.255.255.224, which as every up-and-coming CCNA knows is the network ID for that subnet: 10.10.10.32. Back when I was teaching Cisco classes full-time, I used to have a never-ending argument with another instructor about the fact that I didn't teach bitwise operations as part of subnetting: my position was that if all you are doing is solving subnet problems with your squishy human brain, you don't need to learn a bunch of truth tables when there are easier ways to do it in human memory. However, if you're writing code you actually do need to do bitwise operations.
Unfortunately most of us (me included) aren't wired for reading IPv4 addresses in hex. So I started wondering how little Python code I could use to calculate network IDs for IPv4 in dotted decimal. A little screwing around and I started wondering if I could fit the entire thing into a Twitter post. Here's what I came up with:
Try it:
Now I realize this bit of code is neither particularly clever nor easy to read, which makes it bad code. But hey, it fits in a single tweet. It works by using one of Python's coolest features, the list comprehension. If we start with the innermost parts, it makes more sense:
These two sections return lists of integers corresponding to the address and mask the user enters. For example:
Next, the "zip" function returns a list of tuples that pair corresponding entries in the two lists:
Next, the outermost list comprehension performs a bitwise-AND of each tuple, returning the octets of our network ID in a new list:
Finally, the "join" method puts them back together into "1.1.1.32", and "while 1:" makes it a loop until you ctrl-c out of it.
Working with netmasks in CIDR notation is a bit more complicated, and requires more than one line of code--I'll save that for another post.
jswan$ python
Python 2.7.2 (v2.7.2:8527427914a2, Jun 11 2011, 15:22:34)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 0x78f
1935
>>> hex(1935)
'0x78f'
The topic of numeric base conversions often makes my mind drift to every former networking instructor's pet topics, IPv4 subnetting. The other day, I started playing with using the Python interpreter to find network IDs, which is really easy as long as you're using hex:
>>> hex(0x0a0a0a25 & 0xffffffe0)
'0xa0a0a20'
This little snippet finds the bitwise-AND of 10.10.10.37 and 255.255.255.224, which as every up-and-coming CCNA knows is the network ID for that subnet: 10.10.10.32. Back when I was teaching Cisco classes full-time, I used to have a never-ending argument with another instructor about the fact that I didn't teach bitwise operations as part of subnetting: my position was that if all you are doing is solving subnet problems with your squishy human brain, you don't need to learn a bunch of truth tables when there are easier ways to do it in human memory. However, if you're writing code you actually do need to do bitwise operations.
Unfortunately most of us (me included) aren't wired for reading IPv4 addresses in hex. So I started wondering how little Python code I could use to calculate network IDs for IPv4 in dotted decimal. A little screwing around and I started wondering if I could fit the entire thing into a Twitter post. Here's what I came up with:
while 1:'.'.join([str(a&m)for a,m in zip([int(n)for n in raw_input('addr?').split('.')],[int(n)for n in raw_input('mask?').split('.')])])
Try it:
addr?1.1.1.37
mask?255.255.255.224
'1.1.1.32'
Now I realize this bit of code is neither particularly clever nor easy to read, which makes it bad code. But hey, it fits in a single tweet. It works by using one of Python's coolest features, the list comprehension. If we start with the innermost parts, it makes more sense:
[int(n) for n in raw_input('addr?').split('.')]
[int(n) for n in raw_input('addr?').split('.')]
These two sections return lists of integers corresponding to the address and mask the user enters. For example:
[1,1,1,37]
[255,255,255,224]
Next, the "zip" function returns a list of tuples that pair corresponding entries in the two lists:
[(1, 255), (1, 255), (1, 255), (37, 224)]
Next, the outermost list comprehension performs a bitwise-AND of each tuple, returning the octets of our network ID in a new list:
[1,1,1,32]
Finally, the "join" method puts them back together into "1.1.1.32", and "while 1:" makes it a loop until you ctrl-c out of it.
Working with netmasks in CIDR notation is a bit more complicated, and requires more than one line of code--I'll save that for another post.
Wednesday, December 21, 2011
Find Unique Interface Configs on Switches
Recently I needed to find all of the interfaces with non-standard configurations on a bunch of Catalyst 3750 switches. I wrote a simple Python script to automate the process. To run this, save it in a directory with all of the configurations you want to check. Then edit the name.startswith() section near the bottom to match the naming convention for your config files; in my case all of my configs start with "c3750". Then run the script from your CLI:
If you're on a Mac or Linux system, Python should be installed by default. On Windows, you'll need to install it or run Cygwin. Note that in the default version, the script ignores SVIs and Gigabit interfaces; uncomment the appropriate lines to include them.
The output looks like this:
>python dup_conf.py
If you're on a Mac or Linux system, Python should be installed by default. On Windows, you'll need to install it or run Cygwin. Note that in the default version, the script ignores SVIs and Gigabit interfaces; uncomment the appropriate lines to include them.
The output looks like this:
in config file c3750-1A.txt
interfaces
interface FastEthernet1/0/35
configured like
switchport trunk encapsulation dot1q
switchport trunk native vlan 76
switchport mode trunk
switchport voice vlan 65
no logging event link-status
srr-queue bandwidth share 10 10 60 20
srr-queue bandwidth shape 10 0 0 0
mls qos trust device cisco-phone
mls qos trust dscp
auto qos voip cisco-phone
no mdix auto
spanning-tree portfast
**************************************************
interfaces
interface FastEthernet1/0/11
interface FastEthernet1/0/12
configured like
switchport trunk encapsulation dot1q
switchport trunk native vlan 80
switchport mode trunk
switchport voice vlan 65
srr-queue bandwidth share 10 10 60 20
srr-queue bandwidth shape 10 0 0 0
mls qos trust device cisco-phone
mls qos trust dscp
auto qos voip cisco-phone
no mdix auto
spanning-tree portfast
**************************************************
interfaces
interface FastEthernet1/0/1
interface FastEthernet1/0/2
interface FastEthernet1/0/3
interface FastEthernet1/0/4
interface FastEthernet1/0/5
interface FastEthernet1/0/6
interface FastEthernet1/0/7
interface FastEthernet1/0/8
interface FastEthernet1/0/9
interface FastEthernet1/0/10
interface FastEthernet1/0/13
interface FastEthernet1/0/14
interface FastEthernet1/0/15
interface FastEthernet1/0/16
configured like
switchport access vlan 64
switchport voice vlan 65
srr-queue bandwidth share 10 10 60 20
srr-queue bandwidth shape 10 0 0 0
mls qos trust device cisco-phone
mls qos trust dscp
auto qos voip cisco-phone
no mdix auto
spanning-tree portfast
**************************************************
Thursday, November 10, 2011
Summarize Router Throughput in Packets/Second
Here's a quick one-liner to summarize the current packets-per-second throughput on an entire IOS router:
$ ssh 10.1.2.3 'sh int summ' | awk '/^*/{RXPPS+=$8;TXPPS+=$10} END {print "RXPPS=" RXPPS,"TXPPS=" TXPPS}'
jswan@10.1.2.3's password:
RXPPS=1613 TXPPS=1539
$ ssh 10.1.2.3 'sh int summ' | awk '/^*/{RXPPS+=$8;TXPPS+=$10} END {print "RXPPS=" RXPPS,"TXPPS=" TXPPS}'
jswan@10.1.2.3's password:
RXPPS=1613 TXPPS=1539
Friday, June 10, 2011
Zone Based Firewall Configuration Example
There aren’t a ton of examples available for IOS Zone-Based Firewall configurations, so I thought I’d put up one with which I’ve been working recently.
My test network looks like this:
R4 ------------------- R5 ----------------------- R6
R4 Loopback: 4.4.4.4
R4 to R5 link: 1.1.45.0/24
R5 Loopback: 5.5.5.5
R5 to R6 link: 1.1.56.0/24
R6 Loopback: 6.6.6.6
My goal is to express this policy:
- Hosts in group X on the OUTSIDE network can initiate sessions to hosts on the INSIDE network. Return traffic for those sessions should be statefully permitted. In the lab, group X is represented by R4's loopback address.
- Any host on the INSIDE network can initiate sessions to hosts in group X on the OUTSIDE network. Return traffic for those sessions should be statefully permitted. In the lab, the inside hosts are represented by R6's loopback address.
- Permitted traffic should be logged. All other traffic should be dropped and logged.
The network on which the production version of this lab test will be deployed currently uses extended access-lists to implement the policy. Access-lists have the advantage of being familiar to anyone with a basic knowledge of IOS, but they have a lot of disadvantages:
- Hard to read and troubleshoot as they grow.
- No stateful awareness. Trying to retrofit statefulness onto extended ACLs to allow return traffic requires ugly hacks with source port restrictions, filtering on ACK bits, etc. This path eventually leads to mind-numbing troubleshooting problems, and is less than optimal in its security.
- Extended ACLs don’t have application-layer awareness.
There are several tools in IOS to facilitate stateful traffic inspection, but Zone-Based Firewalls are the newest and most flexible, so it made sense to use them.
Most of the examples I found via Google show the simple case of inside hosts having unfettered access to the outside, and outside hosts having no access to the inside--a classic stateful firewall design. My case is only slightly more complex, but it still took me a couple of tries to make it work.
First, I built access-lists defining the traffic to be allowed. I decided to use the relatively new IOS object-group support to make it easier to add and delete hosts on the respective networks:
object-group network OG_INSIDE_HOSTS
host 6.6.6.6
object-group network OG_OUTSIDE_ALLOWED
host 4.4.4.4
ip access-list extended INSIDE_TO_OUTSIDE
permit ip object-group OG_INSIDE_HOSTS object-group OG_OUTSIDE_ALLOWED
ip access-list extended OUTSIDE_TO_INSIDE
permit ip object-group OG_OUTSIDE_ALLOWED object-group OG_INSIDE_HOSTS
You might notice that there’s no “deny ip any any log” statement in these ACLs, which is strange given requirement #3 above. It turns out that when using ZBFW, you configure drop logging elsewhere; I’ll cover that below.
I couldn’t find a way to express protocol inspection policy and IPv4 address policy in the same class-map, so I had to use a hierarchical configuration. To express the protocol inspection policy, I built a class-map to define the layer 4 protocols that will be inspected by the firewall:
class-map type inspect match-any CM_INSPECTED_PROTOCOLS
match protocol icmp
match protocol tcp
match protocol udp
This class-map does simple generic TCP/UDP/ICMP inspection, but it could easily be extended or rewritten to use much more complex inspection rules.
Next, I built class-maps for each direction that match the appropriate ACL and the inspection policy configured above:
class-map type inspect match-all CM_OUTSIDE_INSIDE
match access-group name OUTSIDE_TO_INSIDE
match class-map CM_INSPECTED_PROTOCOLS
class-map type inspect match-all CM_INSIDE_OUTSIDE
match access-group name INSIDE_TO_OUTSIDE
match class-map CM_INSPECTED_PROTOCOLS
To meet the packet permit-log requirement, we need a “parameter-map” that will be applied in the policy-map that references the previous class-maps:
parameter-map type inspect PARAM_AUDIT_LOG
audit-trail on
Next, the class-maps and parameter-map are referenced in a pair of policy-maps:
policy-map type inspect PM_ZBFW_OUTSIDE_INSIDE
class type inspect CM_OUTSIDE_INSIDE
inspect PARAM_AUDIT_LOG
class class-default
drop log
policy-map type inspect PM_ZBFW_INSIDE_OUTSIDE
class type inspect CM_INSIDE_OUTSIDE
inspect PARAM_AUDIT_LOG
class class-default
drop log
Note the “drop log” statement in the final section. Similar to the implicit deny rule in ACLs, ZBFW policies include a class-default with a drop statement. If you want packet drops to be logged, however, you need to explicitly add the “log” parameter to the drop command.
At this point, the policies are configured. Now they need to be linked to interfaces and traffic direction. This is where the “zones” come in:
zone security INSIDE
description to R6
zone security OUTSIDE
description to R4
interface FastEthernet0/0
zone-member security OUTSIDE
interface FastEthernet0/1
zone-member security INSIDE
Finally, I created zone pairs that associate zones, traffic direction, and traffic policy:
zone-pair security ZP_OUTSIDE_INSIDE source OUTSIDE destination INSIDE
service-policy type inspect PM_ZBFW_OUTSIDE_INSIDE
zone-pair security ZP_INSIDE_OUTSIDE source INSIDE destination OUTSIDE
service-policy type inspect PM_ZBFW_INSIDE_OUTSIDE
At this point, the zone-based firewall should be working and ready to test. Based on the policy defined above, traffic from R4’s loopback address should be able to reach R6’s loopback address, but traffic from other interfaces on R4 should be dropped:
R4#ping 6.6.6.6 source 4.4.4.4
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 6.6.6.6, timeout is 2 seconds:
Packet sent with a source address of 4.4.4.4
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/2/4 ms
R4#
R4#ping 6.6.6.6 source 1.1.45.4
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 6.6.6.6, timeout is 2 seconds:
Packet sent with a source address of 1.1.45.4
.....
Success rate is 0 percent (0/5)
So far, this looks good. The log on R5 should verify the results above:
*Jun 10 14:29:02.604: %FW-6-SESS_AUDIT_TRAIL_START: (target:class)-(ZP_OUTSIDE_INSIDE:CM_OUTSIDE_INSIDE):Start icmp session: initiator (4.4.4.4:0) -- responder (6.6.6.6:0)
*Jun 10 14:29:13.100: %FW-6-SESS_AUDIT_TRAIL: (target:class)-(ZP_OUTSIDE_INSIDE:CM_OUTSIDE_INSIDE):Stop icmp session: in
itiator (4.4.4.4:8) sent 360 bytes -- responder (6.6.6.6:0) sent 360 bytes
*Jun 10 14:29:16.420: %FW-6-DROP_PKT: Dropping icmp session 1.1.45.4:0 6.6.6.6:0 on zone-pair ZP_OUTSIDE_INSIDE class class-default due to DROP action found in policy-map with ip ident 0
*Jun 10 14:29:19.812: %FW-6-LOG_SUMMARY: 2 packets were dropped from 1.1.45.4:8 => 6.6.6.6:0 (target:class)-(ZP_OUTSIDE_INSIDE:class-default)
The first two lines show the permitted session; the second pair of lines show the dropped session. I haven’t had the chance yet to examine log entries for traffic types other than TCP/UDP/ICMP, but at first glance it looks like the log entries are formatted in a way that’s friendly to machine parsing.
My next step should probably be to get the Cisco Press eBook on ZBFW by the formidable Ivan Pepelnjak, which I’m a little embarassed about not having read.
Sunday, May 22, 2011
Links of Interest
I decided to start a periodic link post, mainly to keep track of tech stuff I might want to reference again later.
HTTP Load Testing
Website Security for Webmasters
Reading List on Bayesian Methods
JavaScript PC Emulator < Run VMs in your browser?! We live in the future!
Machine Learning: A Love Story a talk by Hilary Mason
HTTP Load Testing
Website Security for Webmasters
Reading List on Bayesian Methods
JavaScript PC Emulator < Run VMs in your browser?! We live in the future!
Machine Learning: A Love Story a talk by Hilary Mason
Friday, May 13, 2011
Reverse DNS Lookups with Python
Update 12/22/2014 -- Today I would recommend using the dnspython module instead of PyDNS.
I am neither a professional programmer nor a Python expert, but it's currently my language of choice for quick log parsing projects. I couldn't find an example of how to do reverse DNS queries from the PyDNS library, so I figured I'd post my solution here.
First, install the PyDNS library. Python has some native DNS stuff, but PyDNS just seems a lot nicer overall.
Here's my code to do a PTR query, looking up a IPv4 address to find the corresponding DNS name. This code implements a global dictionary of addresses that have been previously resolved, avoiding the need to query the server repeatedly for the same address. You could remove that part if you're feeding a set of unique addresses into the function.
import DNS
SERVER = '8.8.8.8' # put your DNS server address here
global ptr_cache
ptr_cache = {}
def get_ptr(address):
# check cache.
if ptr_cache.has_key(address):
return ptr_cache[address]
#reverse fields in IP address for use with in-addr.arpa query
fields = address.split('.')
fields.reverse()
flippedaddr = '.'.join(fields)
# check cache.
if ptr_cache.has_key(address):
return ptr_cache[address]
#reverse fields in IP address for use with in-addr.arpa query
fields = address.split('.')
fields.reverse()
flippedaddr = '.'.join(fields)
#query DNS
d = DNS.DnsRequest(server=DNS_SERVER,timeout=1)
try:
r = d.req(flippedaddr+'.in-addr.arpa',qtype='PTR')
r = d.req(flippedaddr+'.in-addr.arpa',qtype='PTR')
except:
return "DNS Error"
name = r.answers[0]['data']
if name:
ptr_cache[address] = name
return name
return "DNS Error"
name = r.answers[0]['data']
if name:
ptr_cache[address] = name
return name
Friday, April 8, 2011
Converting text to number in Excel
It took me too long to figure out how to typecast a string to a number in Excel. Preserving it here for posterity; use the "=VALUE()" function.
Wednesday, January 12, 2011
Find Active Hostnames Per Network
Here's a quick trick I use to find the hostnames of all active IPv4 devices in a subnet:
Translated into English:
$ ssh routerIP.test.local 'sh arp | i Vlan70' | awk '{print $2}' | xargs -i dig -x {} +short
Password:
foo-tstsrv-01.test.local.
foo-gissrv-01.test.local.
foo-appsrv-01.test.local.
foo-filsrv-03.test.local.
foo-filsrv-02.test.local.
foo-gissrv-01.test.local.
foo-appsrv-01.test.local.
foo-filsrv-03.test.local.
foo-filsrv-02.test.local.
Translated into English:
- ssh routerIP.test.local 'sh arp | i Vlan70' displays the ARP table for Vlan 70 on the router acting as the default gateway for that VLAN.
- awk '{print $2}' extracts the second field from the output, which is the IPv4 address for the ARP entry.
- xargs -i dig -x {} +short takes each one of those IPv4 addresses and queries DNS for the hostname associated with the IP address (that is, the PTR record), using the "dig -x" command, with the +short parameter to display only the hostname. The {} syntax is a part of the xargs command which causes the output from the previous command (that is, the awk command output which produces just an IPv4 address) to be inserted in the place of the {} characters.
Tuesday, January 4, 2011
Troubleshoot Your Corporate-Speak
A friend of mine recently told me that I "have a hang-up about the meanings of words".
Guilty as charged. I just read yet another press release that uses the idiotic expression "best-of-breed"--I'm at the point where seeing that phrase makes me want to throw a rock at the monitor.
Here's a simple test for a CorporateSpeak buzzphrase: could you say the opposite, without sounding like a crazy person? If not, then your buzzphrase is meaningless. For example:
"Best-of-Breed Vendors Offer Tested and Validated Solutions for Multiple Cisco VXI Deployment Options"
Now, try the opposite:
"Mediocre Vendors With More Successful Competitors Offer Tested and Validated Solutions for Multiple Cisco VXI Deployment Options"
or
"Worst-of-Breed Vendors Offer Tested and Validated Solutions for Multiple Cisco VXI Deployment Options"
No sane person would write that. Thus, the result of the test is that the changed phrase, "best-of-breed", obscures rather than enhances meaning.
Another one I hear all the time is "IT should work to serve the needs of the business." This one doesn't have any suspicious buzzphrases in it, but it's still completely meaningless: can you imagine saying "IT should not work to serve the needs of the business"? Of course not; you'd sound insane. Compare that with a similar, but meaningful and concrete sentence: "IT should work to reduce costs by improving the performance of the accounting servers." With this sentence, IT is still "serving the needs of the business", but you could clearly state the opposite and still have meaning: one could certainly argue that IT's efforts are better spent in areas other than accounting without sounding crazy.
One final example from a friend at a software firm. He received this in email from a guy in sales:
"We need to write software that customers want to buy."
The utter poverty of meaning in that waste of bits is left as an exercise for the reader.
Now, I realize that these sorts of expressions have purposes other than enhancing meaning: they might serve to solicit agreement from the reader as a prelude to a more controversial assertion, or they might simply be not-so-subtle attempts at marketing tricking the reader into a positive first impression. I don't really accept those excuses, though: rational people seek to create meaning, not to obscure it. Get into the habit of troubleshooting your meaning. One way is to test the opposite.
Endnote:
I have no idea if this idea is original or not. It seems like a simple enough idea that I may have gotten it from someone else, but if so, I don't remember and can't attribute the source.
Friday, December 17, 2010
Generate DNS Import from Solarwinds Orion NCM
It's nice to have entries in your internal DNS for router interface names; it makes stuff like traceroute a whole lot easier to read. Many small-to-mid-size companies use Solarwinds products for network management.
This perl script takes the output that you get from using Solarwinds Network Configuration Manager to run the "show ip interface brief | exclude unassigned" command on a group of Cisco IOS devices and massages it into a format that looks like this:
hostname-interfaceName-interfaceNumber a.b.c.d
where a.b.c.d is the IP address assigned to the interface. This format is suitable for import into many DNS servers.
This code doesn't attempt to abbreviate interface names at all, but it could easily be modified to do so.
I run this on Windows using Cygwin and it works fine. The only caveat is that you need to have the dig command installed.
#!/usr/bin/perl
#
# takes output from a Solarwinds Orion NCM command script
# that runs "show ip interface brief | exclude unassigned"
# and produces a "hostname IP" output for import into DNS
# this makes traceroutes more readable
#
# usage: ./interface2dns.pl < inputfile.txt
# inputfile.txt will look like this
# when produced by Orion NCM 6.x:
#
# routerA.test.com (10.38.16.126)
# Interface IP-Address OK? Method Status Protocol
# Loopback0 172.29.255.1 YES NVRAM up up
# Vlan163 10.38.16.126 YES NVRAM up up
# Vlan165 10.38.16.117 YES NVRAM up up
#
#
while (<>){
chomp; # remove newline characters
# find the line with the hostname in it by searching
# for the "(" character
if ($_=~/\(/) {
# split that line on the . character
@hostnameFields = split /\./,$_;
# hostname is the first element before the first .
$hostname=$hostnameFields[0];
}
# identify lines with "up" in them to remove garbage
if ($_=~/\s+up\s+/) {
#split the good lines into space-separated fields
@fields=split /\s+/,$_;
#find RFC1918-like addresses only
if ($fields[1]=~/^10\.|172\.|192\./){
# skip IP addresses that are already in DNS
unless (`dig -x $fields[1] +short`) {
#substitute - for / and : in dns names
$fields[0]=~s/\/|:/-/g;
#print in "hostname-interface ipaddr" format
print "$hostname-$fields[0] $fields[1]\n";
}
}
}
}
This perl script takes the output that you get from using Solarwinds Network Configuration Manager to run the "show ip interface brief | exclude unassigned" command on a group of Cisco IOS devices and massages it into a format that looks like this:
hostname-interfaceName-interfaceNumber a.b.c.d
where a.b.c.d is the IP address assigned to the interface. This format is suitable for import into many DNS servers.
This code doesn't attempt to abbreviate interface names at all, but it could easily be modified to do so.
I run this on Windows using Cygwin and it works fine. The only caveat is that you need to have the dig command installed.
#
# takes output from a Solarwinds Orion NCM command script
# that runs "show ip interface brief | exclude unassigned"
# and produces a "hostname IP" output for import into DNS
# this makes traceroutes more readable
#
# usage: ./interface2dns.pl < inputfile.txt
# inputfile.txt will look like this
# when produced by Orion NCM 6.x:
#
# routerA.test.com (10.38.16.126)
# Interface IP-Address OK? Method Status Protocol
# Loopback0 172.29.255.1 YES NVRAM up up
# Vlan163 10.38.16.126 YES NVRAM up up
# Vlan165 10.38.16.117 YES NVRAM up up
#
#
while (<>){
chomp; # remove newline characters
# find the line with the hostname in it by searching
# for the "(" character
if ($_=~/\(/) {
# split that line on the . character
@hostnameFields = split /\./,$_;
# hostname is the first element before the first .
$hostname=$hostnameFields[0];
}
# identify lines with "up" in them to remove garbage
if ($_=~/\s+up\s+/) {
#split the good lines into space-separated fields
@fields=split /\s+/,$_;
#find RFC1918-like addresses only
if ($fields[1]=~/^10\.|172\.|192\./){
# skip IP addresses that are already in DNS
unless (`dig -x $fields[1] +short`) {
#substitute - for / and : in dns names
$fields[0]=~s/\/|:/-/g;
#print in "hostname-interface ipaddr" format
print "$hostname-$fields[0] $fields[1]\n";
}
}
}
}
Subscribe to:
Posts (Atom)