Skip to content

Commit 41bba8d

Browse files
committed
route: add support for the manipulation of routing informaion
This change adds the Marshal method of RouteMessage to make it possible to exchange route messages between userspace processes and the kernel for the manipulation of routing information base inside the kernel. Change-Id: I0cf2c1a391820f41eb9c5eac1c172598cb2e1533 Reviewed-on: https://go-review.googlesource.com/36077 Reviewed-by: Ian Lance Taylor <iant@golang.org>
1 parent 007e530 commit 41bba8d

24 files changed

+601
-111
lines changed

route/address.go

Lines changed: 148 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,39 @@ type LinkAddr struct {
2424
// Family implements the Family method of Addr interface.
2525
func (a *LinkAddr) Family() int { return sysAF_LINK }
2626

27+
func (a *LinkAddr) lenAndSpace() (int, int) {
28+
l := 8 + len(a.Name) + len(a.Addr)
29+
return l, roundup(l)
30+
}
31+
32+
func (a *LinkAddr) marshal(b []byte) (int, error) {
33+
l, ll := a.lenAndSpace()
34+
if len(b) < ll {
35+
return 0, errShortBuffer
36+
}
37+
nlen, alen := len(a.Name), len(a.Addr)
38+
if nlen > 255 || alen > 255 {
39+
return 0, errInvalidAddr
40+
}
41+
b[0] = byte(l)
42+
b[1] = sysAF_LINK
43+
if a.Index > 0 {
44+
nativeEndian.PutUint16(b[2:4], uint16(a.Index))
45+
}
46+
data := b[8:]
47+
if nlen > 0 {
48+
b[5] = byte(nlen)
49+
copy(data[:nlen], a.Addr)
50+
data = data[nlen:]
51+
}
52+
if alen > 0 {
53+
b[6] = byte(alen)
54+
copy(data[:alen], a.Name)
55+
data = data[alen:]
56+
}
57+
return ll, nil
58+
}
59+
2760
func parseLinkAddr(b []byte) (Addr, error) {
2861
if len(b) < 8 {
2962
return nil, errInvalidAddr
@@ -90,6 +123,21 @@ type Inet4Addr struct {
90123
// Family implements the Family method of Addr interface.
91124
func (a *Inet4Addr) Family() int { return sysAF_INET }
92125

126+
func (a *Inet4Addr) lenAndSpace() (int, int) {
127+
return sizeofSockaddrInet, roundup(sizeofSockaddrInet)
128+
}
129+
130+
func (a *Inet4Addr) marshal(b []byte) (int, error) {
131+
l, ll := a.lenAndSpace()
132+
if len(b) < ll {
133+
return 0, errShortBuffer
134+
}
135+
b[0] = byte(l)
136+
b[1] = sysAF_INET
137+
copy(b[4:8], a.IP[:])
138+
return ll, nil
139+
}
140+
93141
// An Inet6Addr represents an internet address for IPv6.
94142
type Inet6Addr struct {
95143
IP [16]byte // IP address
@@ -99,18 +147,36 @@ type Inet6Addr struct {
99147
// Family implements the Family method of Addr interface.
100148
func (a *Inet6Addr) Family() int { return sysAF_INET6 }
101149

150+
func (a *Inet6Addr) lenAndSpace() (int, int) {
151+
return sizeofSockaddrInet6, roundup(sizeofSockaddrInet6)
152+
}
153+
154+
func (a *Inet6Addr) marshal(b []byte) (int, error) {
155+
l, ll := a.lenAndSpace()
156+
if len(b) < ll {
157+
return 0, errShortBuffer
158+
}
159+
b[0] = byte(l)
160+
b[1] = sysAF_INET6
161+
copy(b[8:24], a.IP[:])
162+
if a.ZoneID > 0 {
163+
nativeEndian.PutUint32(b[24:28], uint32(a.ZoneID))
164+
}
165+
return ll, nil
166+
}
167+
102168
// parseInetAddr parses b as an internet address for IPv4 or IPv6.
103169
func parseInetAddr(af int, b []byte) (Addr, error) {
104170
switch af {
105171
case sysAF_INET:
106-
if len(b) < 16 {
172+
if len(b) < sizeofSockaddrInet {
107173
return nil, errInvalidAddr
108174
}
109175
a := &Inet4Addr{}
110176
copy(a.IP[:], b[4:8])
111177
return a, nil
112178
case sysAF_INET6:
113-
if len(b) < 28 {
179+
if len(b) < sizeofSockaddrInet6 {
114180
return nil, errInvalidAddr
115181
}
116182
a := &Inet6Addr{ZoneID: int(nativeEndian.Uint32(b[24:28]))}
@@ -174,7 +240,7 @@ func parseKernelInetAddr(af int, b []byte) (int, Addr, error) {
174240
off6 = 8 // offset of in6_addr
175241
)
176242
switch {
177-
case b[0] == 28: // size of sockaddr_in6
243+
case b[0] == sizeofSockaddrInet6:
178244
a := &Inet6Addr{}
179245
copy(a.IP[:], b[off6:off6+16])
180246
return int(b[0]), a, nil
@@ -186,7 +252,7 @@ func parseKernelInetAddr(af int, b []byte) (int, Addr, error) {
186252
copy(a.IP[:], b[l-off6:l])
187253
}
188254
return int(b[0]), a, nil
189-
case b[0] == 16: // size of sockaddr_in
255+
case b[0] == sizeofSockaddrInet:
190256
a := &Inet4Addr{}
191257
copy(a.IP[:], b[off4:off4+4])
192258
return int(b[0]), a, nil
@@ -211,6 +277,24 @@ type DefaultAddr struct {
211277
// Family implements the Family method of Addr interface.
212278
func (a *DefaultAddr) Family() int { return a.af }
213279

280+
func (a *DefaultAddr) lenAndSpace() (int, int) {
281+
l := len(a.Raw)
282+
return l, roundup(l)
283+
}
284+
285+
func (a *DefaultAddr) marshal(b []byte) (int, error) {
286+
l, ll := a.lenAndSpace()
287+
if len(b) < ll {
288+
return 0, errShortBuffer
289+
}
290+
if l > 255 {
291+
return 0, errInvalidAddr
292+
}
293+
b[1] = byte(l)
294+
copy(b[:l], a.Raw)
295+
return ll, nil
296+
}
297+
214298
func parseDefaultAddr(b []byte) (Addr, error) {
215299
if len(b) < 2 || len(b) < int(b[0]) {
216300
return nil, errInvalidAddr
@@ -219,6 +303,66 @@ func parseDefaultAddr(b []byte) (Addr, error) {
219303
return a, nil
220304
}
221305

306+
func addrsSpace(as []Addr) int {
307+
var l int
308+
for _, a := range as {
309+
switch a := a.(type) {
310+
case *LinkAddr:
311+
_, ll := a.lenAndSpace()
312+
l += ll
313+
case *Inet4Addr:
314+
_, ll := a.lenAndSpace()
315+
l += ll
316+
case *Inet6Addr:
317+
_, ll := a.lenAndSpace()
318+
l += ll
319+
case *DefaultAddr:
320+
_, ll := a.lenAndSpace()
321+
l += ll
322+
}
323+
}
324+
return l
325+
}
326+
327+
// marshalAddrs marshals as returns a bitmap indicating which address
328+
// is stored in b.
329+
func marshalAddrs(b []byte, as []Addr) (uint, error) {
330+
var attrs uint
331+
for i, a := range as {
332+
switch a := a.(type) {
333+
case *LinkAddr:
334+
l, err := a.marshal(b)
335+
if err != nil {
336+
return 0, err
337+
}
338+
b = b[l:]
339+
attrs |= 1 << uint(i)
340+
case *Inet4Addr:
341+
l, err := a.marshal(b)
342+
if err != nil {
343+
return 0, err
344+
}
345+
b = b[l:]
346+
attrs |= 1 << uint(i)
347+
case *Inet6Addr:
348+
l, err := a.marshal(b)
349+
if err != nil {
350+
return 0, err
351+
}
352+
b = b[l:]
353+
attrs |= 1 << uint(i)
354+
case *DefaultAddr:
355+
l, err := a.marshal(b)
356+
if err != nil {
357+
return 0, err
358+
}
359+
b = b[l:]
360+
attrs |= 1 << uint(i)
361+
}
362+
}
363+
return attrs, nil
364+
}
365+
222366
func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ([]Addr, error) {
223367
var as [sysRTAX_MAX]Addr
224368
af := int(sysAF_UNSPEC)

route/defs_darwin.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ package route
1313
#include <net/if.h>
1414
#include <net/if_dl.h>
1515
#include <net/route.h>
16+
17+
#include <netinet/in.h>
1618
*/
1719
import "C"
1820

@@ -23,6 +25,8 @@ const (
2325
sysAF_LINK = C.AF_LINK
2426
sysAF_INET6 = C.AF_INET6
2527

28+
sysSOCK_RAW = C.SOCK_RAW
29+
2630
sysNET_RT_DUMP = C.NET_RT_DUMP
2731
sysNET_RT_FLAGS = C.NET_RT_FLAGS
2832
sysNET_RT_IFLIST = C.NET_RT_IFLIST
@@ -103,4 +107,8 @@ const (
103107
sizeofRtMsghdrDarwin15 = C.sizeof_struct_rt_msghdr
104108
sizeofRtMsghdr2Darwin15 = C.sizeof_struct_rt_msghdr2
105109
sizeofRtMetricsDarwin15 = C.sizeof_struct_rt_metrics
110+
111+
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
112+
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
113+
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
106114
)

route/defs_dragonfly.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ package route
1313
#include <net/if.h>
1414
#include <net/if_dl.h>
1515
#include <net/route.h>
16+
17+
#include <netinet/in.h>
1618
*/
1719
import "C"
1820

@@ -23,6 +25,8 @@ const (
2325
sysAF_LINK = C.AF_LINK
2426
sysAF_INET6 = C.AF_INET6
2527

28+
sysSOCK_RAW = C.SOCK_RAW
29+
2630
sysNET_RT_DUMP = C.NET_RT_DUMP
2731
sysNET_RT_FLAGS = C.NET_RT_FLAGS
2832
sysNET_RT_IFLIST = C.NET_RT_IFLIST
@@ -102,4 +106,8 @@ const (
102106

103107
sizeofRtMsghdrDragonFlyBSD4 = C.sizeof_struct_rt_msghdr
104108
sizeofRtMetricsDragonFlyBSD4 = C.sizeof_struct_rt_metrics
109+
110+
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
111+
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
112+
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
105113
)

route/defs_freebsd.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ package route
1414
#include <net/if_dl.h>
1515
#include <net/route.h>
1616
17+
#include <netinet/in.h>
18+
1719
struct if_data_freebsd7 {
1820
u_char ifi_type;
1921
u_char ifi_physical;
@@ -222,6 +224,8 @@ const (
222224
sysAF_LINK = C.AF_LINK
223225
sysAF_INET6 = C.AF_INET6
224226

227+
sysSOCK_RAW = C.SOCK_RAW
228+
225229
sysNET_RT_DUMP = C.NET_RT_DUMP
226230
sysNET_RT_FLAGS = C.NET_RT_FLAGS
227231
sysNET_RT_IFLIST = C.NET_RT_IFLIST
@@ -326,4 +330,8 @@ const (
326330
sizeofIfDataFreeBSD9Emu = C.sizeof_struct_if_data_freebsd9
327331
sizeofIfDataFreeBSD10Emu = C.sizeof_struct_if_data_freebsd10
328332
sizeofIfDataFreeBSD11Emu = C.sizeof_struct_if_data_freebsd11
333+
334+
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
335+
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
336+
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
329337
)

route/defs_netbsd.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ package route
1313
#include <net/if.h>
1414
#include <net/if_dl.h>
1515
#include <net/route.h>
16+
17+
#include <netinet/in.h>
1618
*/
1719
import "C"
1820

@@ -23,6 +25,8 @@ const (
2325
sysAF_LINK = C.AF_LINK
2426
sysAF_INET6 = C.AF_INET6
2527

28+
sysSOCK_RAW = C.SOCK_RAW
29+
2630
sysNET_RT_DUMP = C.NET_RT_DUMP
2731
sysNET_RT_FLAGS = C.NET_RT_FLAGS
2832
sysNET_RT_IFLIST = C.NET_RT_IFLIST
@@ -101,4 +105,8 @@ const (
101105

102106
sizeofRtMsghdrNetBSD7 = C.sizeof_struct_rt_msghdr
103107
sizeofRtMetricsNetBSD7 = C.sizeof_struct_rt_metrics
108+
109+
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
110+
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
111+
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
104112
)

route/defs_openbsd.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ package route
1313
#include <net/if.h>
1414
#include <net/if_dl.h>
1515
#include <net/route.h>
16+
17+
#include <netinet/in.h>
1618
*/
1719
import "C"
1820

@@ -23,6 +25,8 @@ const (
2325
sysAF_LINK = C.AF_LINK
2426
sysAF_INET6 = C.AF_INET6
2527

28+
sysSOCK_RAW = C.SOCK_RAW
29+
2630
sysNET_RT_DUMP = C.NET_RT_DUMP
2731
sysNET_RT_FLAGS = C.NET_RT_FLAGS
2832
sysNET_RT_IFLIST = C.NET_RT_IFLIST
@@ -91,3 +95,11 @@ const (
9195
sysRTAX_LABEL = C.RTAX_LABEL
9296
sysRTAX_MAX = C.RTAX_MAX
9397
)
98+
99+
const (
100+
sizeofRtMsghdr = C.sizeof_struct_rt_msghdr
101+
102+
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
103+
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
104+
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
105+
)

route/message.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
package route
88

99
// A Message represents a routing message.
10-
//
11-
// Note: This interface will be changed to support Marshal method in
12-
// future version.
1310
type Message interface {
1411
// Sys returns operating system-specific information.
1512
Sys() []Sys
@@ -52,11 +49,10 @@ func ParseRIB(typ RIBType, b []byte) ([]Message, error) {
5249
b = b[l:]
5350
continue
5451
}
55-
mtyp := int(b[3])
56-
if fn, ok := parseFns[mtyp]; !ok {
52+
if w, ok := wireFormats[int(b[3])]; !ok {
5753
nskips++
5854
} else {
59-
m, err := fn(typ, b)
55+
m, err := w.parse(typ, b)
6056
if err != nil {
6157
return nil, err
6258
}

0 commit comments

Comments
 (0)