diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index ce56dbf78c621f9a58339fb56c9f0c56d5509287..8960a4c949244ab2ab3438d6d1d7c30697e5368c 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -1,6 +1,6 @@
 {
 	"ImportPath": "github.com/jbenet/go-ipfs",
-	"GoVersion": "go1.3.3",
+	"GoVersion": "go1.3",
 	"Packages": [
 		"./..."
 	],
@@ -102,8 +102,8 @@
 		},
 		{
 			"ImportPath": "github.com/jbenet/go-multiaddr",
-			"Comment": "0.1.2-17-g68a2067",
-			"Rev": "68a20675cb0829da219def0d90afe17a7219e8c7"
+			"Comment": "0.1.2-27-g62a88e0",
+			"Rev": "62a88e015e1bf5d6aaca29aec1aba0722f21c8d3"
 		},
 		{
 			"ImportPath": "github.com/jbenet/go-multihash",
diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/README.md b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/README.md
index 7ff9854f18f38a9c1da58a59bb288f13ce6117b0..f2545485d1f069ec5ef14ddd629f235a9987315d 100644
--- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/README.md
+++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/README.md
@@ -34,16 +34,6 @@ addr.Protocols()
 // }
 ```
 
-### Other formats
-
-```go
-// handles the stupid url version too
-m = ma.NewUrl("udp4://127.0.0.1:1234")
-// <Multiaddr /ip4/127.0.0.1/udp/1234>
-m.Url(buf)
-// udp4://127.0.0.1:1234
-```
-
 ### En/decapsulate
 
 ```go
diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/codec.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/codec.go
index a6cf9911ce3cb7e6a6a2a4313a77aa450311444f..d08544b46a521b283c6ba377afc8037f1515f0d5 100644
--- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/codec.go
+++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/codec.go
@@ -67,6 +67,30 @@ func bytesToString(b []byte) (ret string, err error) {
 	return s, nil
 }
 
+func bytesSplit(b []byte) (ret [][]byte, err error) {
+	// panic handler, in case we try accessing bytes incorrectly.
+	defer func() {
+		if e := recover(); e != nil {
+			ret = [][]byte{}
+			err = e.(error)
+		}
+	}()
+
+	ret = [][]byte{}
+	for len(b) > 0 {
+		p := ProtocolWithCode(int(b[0]))
+		if p == nil {
+			return [][]byte{}, fmt.Errorf("no protocol with code %d", b[0])
+		}
+
+		length := 1 + (p.Size / 8)
+		ret = append(ret, b[:length])
+		b = b[length:]
+	}
+
+	return ret, nil
+}
+
 func addressStringToBytes(p *Protocol, s string) []byte {
 	switch p.Code {
 
diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr.go
index 4ee63ca43bb1949b3d4981dc09f2eb1be1ae21a7..a2bea09addec6365e1be4d52e3652e4555bd7fcb 100644
--- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr.go
+++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr.go
@@ -84,10 +84,10 @@ func (m *multiaddr) Encapsulate(o Multiaddr) Multiaddr {
 	mb := m.bytes
 	ob := o.Bytes()
 
-	var b bytes.Buffer
-	b.Write(mb)
-	b.Write(ob)
-	return &multiaddr{bytes: b.Bytes()}
+	b := make([]byte, len(mb)+len(ob))
+	copy(b, mb)
+	copy(b[len(mb):], ob)
+	return &multiaddr{bytes: b}
 }
 
 // Decapsulate unwraps Multiaddr up until the given Multiaddr is found.
diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr/multiaddr b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr/multiaddr
new file mode 100644
index 0000000000000000000000000000000000000000..c54b3bf0834323c47190c49f9700ed855cf49761
Binary files /dev/null and b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr/multiaddr differ
diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr/multiaddr.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr/multiaddr.go
new file mode 100644
index 0000000000000000000000000000000000000000..441f607a6df4af76675881abc6ca86ac0c3650ff
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr/multiaddr.go
@@ -0,0 +1,96 @@
+package main
+
+import (
+	"encoding/hex"
+	"flag"
+	"fmt"
+	"os"
+
+	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
+	manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net"
+)
+
+// flags
+var formats = []string{"string", "bytes", "hex", "slice"}
+var format string
+var hideLoopback bool
+
+func init() {
+	flag.Usage = func() {
+		fmt.Fprintf(os.Stderr, "usage: %s [<multiaddr>]\n\nFlags:\n", os.Args[0])
+		flag.PrintDefaults()
+	}
+
+	usage := fmt.Sprintf("output format, one of: %v", formats)
+	flag.StringVar(&format, "format", "string", usage)
+	flag.StringVar(&format, "f", "string", usage+" (shorthand)")
+	flag.BoolVar(&hideLoopback, "hide-loopback", false, "do not display loopback addresses")
+}
+
+func main() {
+	flag.Parse()
+	args := flag.Args()
+	if len(args) == 0 {
+		output(localAddresses()...)
+	} else {
+		output(address(args[0]))
+	}
+}
+
+func localAddresses() []ma.Multiaddr {
+	maddrs, err := manet.InterfaceMultiaddrs()
+	if err != nil {
+		die(err)
+	}
+
+	if !hideLoopback {
+		return maddrs
+	}
+
+	var maddrs2 []ma.Multiaddr
+	for _, a := range maddrs {
+		if !manet.IsIPLoopback(a) {
+			maddrs2 = append(maddrs2, a)
+		}
+	}
+
+	return maddrs2
+}
+
+func address(addr string) ma.Multiaddr {
+	m, err := ma.NewMultiaddr(addr)
+	if err != nil {
+		die(err)
+	}
+
+	return m
+}
+
+func output(ms ...ma.Multiaddr) {
+	for _, m := range ms {
+		fmt.Println(outfmt(m))
+	}
+}
+
+func outfmt(m ma.Multiaddr) string {
+	switch format {
+	case "string":
+		return m.String()
+	case "slice":
+		return fmt.Sprintf("%v", m.Bytes())
+	case "bytes":
+		return string(m.Bytes())
+	case "hex":
+		return "0x" + hex.EncodeToString(m.Bytes())
+	}
+
+	die("error: invalid format", format)
+	return ""
+}
+
+func die(v ...interface{}) {
+	fmt.Fprint(os.Stderr, v...)
+	fmt.Fprint(os.Stderr, "\n")
+	flag.Usage()
+	os.Exit(-1)
+}
diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr_test.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr_test.go
index 3a7820400d6f862b50ff7f4ff1aa0ed0da660129..a5cb666a08293028b2397098a50f17f99011eb0b 100644
--- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr_test.go
+++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr_test.go
@@ -91,6 +91,49 @@ func TestBytesToString(t *testing.T) {
 	testString("/ip4/127.0.0.1/udp/1234", "047f0000011104d2")
 }
 
+func TestBytesSplitAndJoin(t *testing.T) {
+
+	testString := func(s string, res []string) {
+		m, err := NewMultiaddr(s)
+		if err != nil {
+			t.Error("failed to convert", s)
+		}
+
+		split := Split(m)
+		if len(split) != len(res) {
+			t.Error("not enough split components", split)
+			return
+		}
+
+		for i, a := range split {
+			if a.String() != res[i] {
+				t.Errorf("split component failed: %s != %s", a, res[i])
+			}
+		}
+
+		joined := Join(split...)
+		if !m.Equal(joined) {
+			t.Errorf("joined components failed: %s != %s", m, joined)
+		}
+
+		// modifying underlying bytes is fine.
+		m2 := m.(*multiaddr)
+		for i := range m2.bytes {
+			m2.bytes[i] = 0
+		}
+
+		for i, a := range split {
+			if a.String() != res[i] {
+				t.Errorf("split component failed: %s != %s", a, res[i])
+			}
+		}
+	}
+
+	testString("/ip4/1.2.3.4/udp/1234", []string{"/ip4/1.2.3.4", "/udp/1234"})
+	testString("/ip4/1.2.3.4/tcp/1/ip4/2.3.4.5/udp/2",
+		[]string{"/ip4/1.2.3.4", "/tcp/1", "/ip4/2.3.4.5", "/udp/2"})
+}
+
 func TestProtocols(t *testing.T) {
 	m, err := NewMultiaddr("/ip4/127.0.0.1/udp/1234")
 	if err != nil {
diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/convert.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/convert.go
index d7749d89dfca9baf311a72f061d712a030edbd77..c28159f84f1ee6bc4990a0806269d264d5347a71 100644
--- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/convert.go
+++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/convert.go
@@ -1,4 +1,4 @@
-package net
+package manet
 
 import (
 	"fmt"
@@ -62,6 +62,13 @@ func FromNetAddr(a net.Addr) (ma.Multiaddr, error) {
 		}
 		return FromIP(ac.IP)
 
+	case "ip+net":
+		ac, ok := a.(*net.IPNet)
+		if !ok {
+			return nil, errIncorrectNetAddr
+		}
+		return FromIP(ac.IP)
+
 	default:
 		return nil, fmt.Errorf("unknown network %v", a.Network())
 	}
@@ -123,30 +130,3 @@ func DialArgs(m ma.Multiaddr) (string, string, error) {
 	}
 	return network, host, nil
 }
-
-// IsThinWaist returns whether a Multiaddr starts with "Thin Waist" Protocols.
-// This means: /{IP4, IP6}[/{TCP, UDP}]
-func IsThinWaist(m ma.Multiaddr) bool {
-	p := m.Protocols()
-
-	// nothing? not even a waist.
-	if len(p) == 0 {
-		return false
-	}
-
-	if p[0].Code != ma.P_IP4 && p[0].Code != ma.P_IP6 {
-		return false
-	}
-
-	// only IP? still counts.
-	if len(p) == 1 {
-		return true
-	}
-
-	switch p[1].Code {
-	case ma.P_TCP, ma.P_UDP, ma.P_IP4, ma.P_IP6:
-		return true
-	default:
-		return false
-	}
-}
diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/convert_test.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/convert_test.go
index 7dc8e50a345738d977747c324db366e9d4c81d4a..47b25e7b9078e1006c8530fcf2c8b368649503c2 100644
--- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/convert_test.go
+++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/convert_test.go
@@ -1,4 +1,4 @@
-package net
+package manet
 
 import (
 	"net"
diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/doc.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/doc.go
index d73b8652ff81fdfb0959a462a77fc43a8d688a7b..040ad3f02fa6cd98f7b14d9499e341eee85f9c94 100644
--- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/doc.go
+++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/doc.go
@@ -1,5 +1,5 @@
-// Package net provides Multiaddr specific versions of common
+// Package manet provides Multiaddr specific versions of common
 // functions in stdlib's net package. This means wrappers of
 // standard net symbols like net.Dial and net.Listen, as well
 // as conversion to/from net.Addr.
-package net
+package manet
diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/ip.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/ip.go
new file mode 100644
index 0000000000000000000000000000000000000000..57d2e38d6ee5156dda68734cb9f6b7f29371b7b3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/ip.go
@@ -0,0 +1,76 @@
+package manet
+
+import (
+	"bytes"
+
+	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
+)
+
+// Loopback Addresses
+var (
+	// IP4Loopback is the ip4 loopback multiaddr
+	IP4Loopback = ma.StringCast("/ip4/127.0.0.1")
+
+	// IP6Loopback is the ip6 loopback multiaddr
+	IP6Loopback = ma.StringCast("/ip6/::1")
+
+	// IP6LinkLocalLoopback is the ip6 link-local loopback multiaddr
+	IP6LinkLocalLoopback = ma.StringCast("/ip6/fe80::1")
+)
+
+// Unspecified Addresses (used for )
+var (
+	IP4Unspecified = ma.StringCast("/ip4/0.0.0.0")
+	IP6Unspecified = ma.StringCast("/ip6/::")
+)
+
+// IsThinWaist returns whether a Multiaddr starts with "Thin Waist" Protocols.
+// This means: /{IP4, IP6}[/{TCP, UDP}]
+func IsThinWaist(m ma.Multiaddr) bool {
+	p := m.Protocols()
+
+	// nothing? not even a waist.
+	if len(p) == 0 {
+		return false
+	}
+
+	if p[0].Code != ma.P_IP4 && p[0].Code != ma.P_IP6 {
+		return false
+	}
+
+	// only IP? still counts.
+	if len(p) == 1 {
+		return true
+	}
+
+	switch p[1].Code {
+	case ma.P_TCP, ma.P_UDP, ma.P_IP4, ma.P_IP6:
+		return true
+	default:
+		return false
+	}
+}
+
+// IsIPLoopback returns whether a Multiaddr is a "Loopback" IP address
+// This means either /ip4/127.0.0.1 or /ip6/::1
+func IsIPLoopback(m ma.Multiaddr) bool {
+	b := m.Bytes()
+
+	// /ip4/127 prefix (_entire_ /8 is loopback...)
+	if bytes.HasPrefix(b, []byte{4, 127}) {
+		return true
+	}
+
+	// /ip6/::1
+	if IP6Loopback.Equal(m) || IP6LinkLocalLoopback.Equal(m) {
+		return true
+	}
+
+	return false
+}
+
+// IsIPUnspecified returns whether a Multiaddr is am Unspecified IP address
+// This means either /ip4/0.0.0.0 or /ip6/::
+func IsIPUnspecified(m ma.Multiaddr) bool {
+	return IP4Unspecified.Equal(m) || IP6Unspecified.Equal(m)
+}
diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/net.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/net.go
index 3cb41622f61d6ea77e4778899646bfc9868cbd87..a4eb0893870ec9914212afb6185b41945b7116d7 100644
--- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/net.go
+++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/net.go
@@ -1,4 +1,4 @@
-package net
+package manet
 
 import (
 	"fmt"
@@ -216,3 +216,20 @@ func Listen(laddr ma.Multiaddr) (Listener, error) {
 		laddr:    laddr,
 	}, nil
 }
+
+// InterfaceMultiaddrs will return the addresses matching net.InterfaceAddrs
+func InterfaceMultiaddrs() ([]ma.Multiaddr, error) {
+	addrs, err := net.InterfaceAddrs()
+	if err != nil {
+		return nil, err
+	}
+
+	maddrs := make([]ma.Multiaddr, len(addrs))
+	for i, a := range addrs {
+		maddrs[i], err = FromNetAddr(a)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return maddrs, nil
+}
diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/net_test.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/net_test.go
index 316a57afae1ca713cf63a09d0513a02c357b46af..46fd7aed4fa5b067a4855ce2c50a630bcc4dc452 100644
--- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/net_test.go
+++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/net_test.go
@@ -1,4 +1,4 @@
-package net
+package manet
 
 import (
 	"bytes"
@@ -198,3 +198,47 @@ func TestListenAndDial(t *testing.T) {
 	cA.Close()
 	wg.Wait()
 }
+
+func TestIPLoopback(t *testing.T) {
+	if IP4Loopback.String() != "/ip4/127.0.0.1" {
+		t.Error("IP4Loopback incorrect:", IP4Loopback)
+	}
+
+	if IP6Loopback.String() != "/ip6/::1" {
+		t.Error("IP6Loopback incorrect:", IP6Loopback)
+	}
+
+	if IP6LinkLocalLoopback.String() != "/ip6/fe80::1" {
+		t.Error("IP6LinkLocalLoopback incorrect:", IP6Loopback)
+	}
+
+	if !IsIPLoopback(IP4Loopback) {
+		t.Error("IsIPLoopback failed (IP4Loopback)")
+	}
+
+	if !IsIPLoopback(IP6Loopback) {
+		t.Error("IsIPLoopback failed (IP6Loopback)")
+	}
+
+	if !IsIPLoopback(IP6LinkLocalLoopback) {
+		t.Error("IsIPLoopback failed (IP6LinkLocalLoopback)")
+	}
+}
+
+func TestIPUnspecified(t *testing.T) {
+	if IP4Unspecified.String() != "/ip4/0.0.0.0" {
+		t.Error("IP4Unspecified incorrect:", IP4Unspecified)
+	}
+
+	if IP6Unspecified.String() != "/ip6/::" {
+		t.Error("IP6Unspecified incorrect:", IP6Unspecified)
+	}
+
+	if !IsIPUnspecified(IP4Unspecified) {
+		t.Error("IsIPUnspecified failed (IP4Unspecified)")
+	}
+
+	if !IsIPUnspecified(IP6Unspecified) {
+		t.Error("IsIPUnspecified failed (IP6Unspecified)")
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/util.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/util.go
new file mode 100644
index 0000000000000000000000000000000000000000..d1b54afbb6a64260c8c5a154e42d0e9a8d03cd6b
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/util.go
@@ -0,0 +1,56 @@
+package multiaddr
+
+import "fmt"
+
+// Split returns the sub-address portions of a multiaddr.
+func Split(m Multiaddr) []Multiaddr {
+	split, err := bytesSplit(m.Bytes())
+	if err != nil {
+		panic(fmt.Errorf("invalid multiaddr %s", m.String()))
+	}
+
+	addrs := make([]Multiaddr, len(split))
+	for i, addr := range split {
+		addrs[i] = &multiaddr{bytes: addr}
+	}
+	return addrs
+}
+
+// Join returns a combination of addresses.
+func Join(ms ...Multiaddr) Multiaddr {
+
+	length := 0
+	bs := make([][]byte, len(ms))
+	for i, m := range ms {
+		bs[i] = m.Bytes()
+		length += len(bs[i])
+	}
+
+	bidx := 0
+	b := make([]byte, length)
+	for _, mb := range bs {
+		for i := range mb {
+			b[bidx] = mb[i]
+			bidx++
+		}
+	}
+	return &multiaddr{bytes: b}
+}
+
+// Cast re-casts a byte slice as a multiaddr. will panic if it fails to parse.
+func Cast(b []byte) Multiaddr {
+	_, err := bytesToString(b)
+	if err != nil {
+		panic(fmt.Errorf("multiaddr failed to parse: %s", err))
+	}
+	return &multiaddr{bytes: b}
+}
+
+// StringCast like Cast, but parses a string. Will also panic if it fails to parse.
+func StringCast(s string) Multiaddr {
+	m, err := NewMultiaddr(s)
+	if err != nil {
+		panic(fmt.Errorf("multiaddr failed to parse: %s", err))
+	}
+	return m
+}