Mr. Script

Many IPs, One NIC? No Problem.

If you've been wanting to bind multiple IP addresses to a single NIC, now you can.

The other day I had to scold my son for trying to take his brother's Popsicle after he'd finished his own. "Don't be greedy," I told him. "You had yours, let Bubba have his." Of course, he started crying, and I felt my resolve wavering. His tears brought me to the verge of my own tears, but I stuck to my guns and he got the message: Greed is bad.

The next day, I received this e-mail from a reader named Prasad: I've been trying to add multiple IP addresses to the same NIC interface using WMI and didn't have any success. On UNIX platforms, this can be easily done using ifconfig. I'm hoping there is an equivalent on Windows, but I couldn't find any.

My first thought was: Why do you need so many IP addresses? You need to share! After I stopped thinking like a father, I realized there were lots of reasons you might want to bind multiple IP addresses to a single NIC. A Web server with multiple virtual servers is one example that comes to mind. So, to answer Prasad's question, "Can it be done?" Why, of course!

A Few Assumptions
Because we're binding multiple IP addresses to a single NIC, we're assuming that it's the only NIC installed. If you have a multi-homed machine, you'll need to take steps to identify the correct NIC. Even if you don't have multiple NICs, you probably do have an IEEE 1394 (Firewire) adapter or other hardware that Windows "sees" as a NIC. As such, we need to filter out devices that don't have IP enabled to ensure that we're configuring the correct NIC.



Multi_IP.wsf
Retrieves IP addresses from a database
and binds them to a single NIC



    <>
id="objConn" progid="ADODB.Connection" Reference/>
    <> id="objRS" progid="ADODB.Recordset" Reference/>
    <> language="VBScript">
      Dim strIPAddr(), strSNMask(), strGW()
objConn.Open "DSN=IPData;"
      objRS.CursorLocation = adUseClient
      objRS.Open "SELECT * FROM IPAddresses", _
        objConn, _
        adOpenStatic, _
        adLockOptimistic

      objRS.MoveFirst
      iRC=objRS.RecordCount
      ReDim strIPAddr(iRC)
      ReDim strSNMask(iRC)
      ReDim strGW(iRC)
      iCount=0
      'Store IP addr, SN mask, and GW into arrays
      Do Until objRS.EOF
        strIPAddr(iCount)=objRS.Fields.Item("IP")
        strSNMask(iCount)=objRS.Fields.Item("Mask")
        strGW(iCount)=objRS.Fields.Item("GW")
        iCount=iCount+1
        objRS.MoveNext
      Loop
      objRS.Close
      objConn.Close

'Bind the addresses to the NIC
      strGWMetric = Array(1)
      Set objWMI =GetObject("winmgmts:\\.\root\cimv2")
      Set colNICs = objWMI.ExecQuery _
        ("Select * from " _
        & "Win32_NetworkAdapterConfiguration " _
        & "where IPEnabled=TRUE")
      For Each objNIC in colNICs
      bErr1 = objNIC.EnableStatic _
        "(strIPAddr, strSNMask)
      bErr2 = objNIC.SetGateways _
        "(strGW, strGWMetric)
      Next
   
  

Two for One
We've used ActiveX Data Objects (ADO) to retrieve the IP address data from an Access database, and connected to that database using a Data Source Name (DSN) rather than connecting directly.

Figure 1 shows the IPAddresses table that holds our data. It may seem like a waste of space to repeat the same subnet mask and default gateway in each row, but by structuring our data this way, it allows for flexibility in case the multiple addresses we're binding happen to belong to different networks (for instance, if this was a notebook computer that connected to several different networks).

Figure 1. Each IP address has a corresponding subnet mask and default gateway.
Figure 1. Each IP address has a corresponding subnet mask and default gateway. (Click image to view larger version.)

Binded by the Light
After reading the data into the arrays, we then bind the multiple IP addresses to the NIC. The good news is that WMI makes this easy. In fact, because the IP Address property is stored as an array, the actual process of binding multiple addresses is exactly the same as binding a single address. The only difference is the size of the array. Speaking of arrays, you'll notice that I used the ReDim keyword to reallocate space for the array once I knew how many records I was dealing with. Anytime you need to allocate array space based on dynamic data, use ReDim. Just remember to declare an empty array (Dim strIPAddr()) first.

You may have valid reasons for not wanting to connect to the database via the DSN. Hey, I'm not here to judge. If you'd rather connect directly, that's your business. Just replace your Open statement with this:

objConn.Open "Provider =
Microsoft.Jet.OLEDB.4.0; Data Source =
C:\IPAddress.mdb"

No Guts, No Glory
Now that you've had a taste of the power of ADO, dive in and really get familiar with it. It adds a whole new dimension to scripting.

About the Author

Chris Brooke, MCSE, is a contributing editor for Redmond magazine and director of enterprise technology for ComponentSource. He specializes in development, integration services and network/Internet administration. Send questions or your favorite scripts to chrisb@componentsource.com.

comments powered by Disqus

Redmond Tech Watch

Sign up for our newsletter.

I agree to this site's Privacy Policy.