Source file src/pkg/syscall/netlink_linux.go
1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Netlink sockets and messages 6 7 package syscall 8 9 import ( 10 "unsafe" 11 ) 12 13 // Round the length of a netlink message up to align it properly. 14 func nlmAlignOf(msglen int) int { 15 return (msglen + NLMSG_ALIGNTO - 1) & ^(NLMSG_ALIGNTO - 1) 16 } 17 18 // Round the length of a netlink route attribute up to align it 19 // properly. 20 func rtaAlignOf(attrlen int) int { 21 return (attrlen + RTA_ALIGNTO - 1) & ^(RTA_ALIGNTO - 1) 22 } 23 24 // NetlinkRouteRequest represents the request message to receive 25 // routing and link states from the kernel. 26 type NetlinkRouteRequest struct { 27 Header NlMsghdr 28 Data RtGenmsg 29 } 30 31 func (rr *NetlinkRouteRequest) toWireFormat() []byte { 32 b := make([]byte, rr.Header.Len) 33 b[0] = byte(rr.Header.Len) 34 b[1] = byte(rr.Header.Len >> 8) 35 b[2] = byte(rr.Header.Len >> 16) 36 b[3] = byte(rr.Header.Len >> 24) 37 b[4] = byte(rr.Header.Type) 38 b[5] = byte(rr.Header.Type >> 8) 39 b[6] = byte(rr.Header.Flags) 40 b[7] = byte(rr.Header.Flags >> 8) 41 b[8] = byte(rr.Header.Seq) 42 b[9] = byte(rr.Header.Seq >> 8) 43 b[10] = byte(rr.Header.Seq >> 16) 44 b[11] = byte(rr.Header.Seq >> 24) 45 b[12] = byte(rr.Header.Pid) 46 b[13] = byte(rr.Header.Pid >> 8) 47 b[14] = byte(rr.Header.Pid >> 16) 48 b[15] = byte(rr.Header.Pid >> 24) 49 b[16] = byte(rr.Data.Family) 50 return b 51 } 52 53 func newNetlinkRouteRequest(proto, seq, family int) []byte { 54 rr := &NetlinkRouteRequest{} 55 rr.Header.Len = NLMSG_HDRLEN + SizeofRtGenmsg 56 rr.Header.Type = uint16(proto) 57 rr.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST 58 rr.Header.Seq = uint32(seq) 59 rr.Data.Family = uint8(family) 60 return rr.toWireFormat() 61 } 62 63 // NetlinkRIB returns routing information base, as known as RIB, 64 // which consists of network facility information, states and 65 // parameters. 66 func NetlinkRIB(proto, family int) ([]byte, error) { 67 var ( 68 lsanl SockaddrNetlink 69 tab []byte 70 ) 71 72 s, e := Socket(AF_NETLINK, SOCK_RAW, 0) 73 if e != nil { 74 return nil, e 75 } 76 defer Close(s) 77 78 lsanl.Family = AF_NETLINK 79 e = Bind(s, &lsanl) 80 if e != nil { 81 return nil, e 82 } 83 84 seq := 1 85 wb := newNetlinkRouteRequest(proto, seq, family) 86 e = Sendto(s, wb, 0, &lsanl) 87 if e != nil { 88 return nil, e 89 } 90 91 for { 92 var ( 93 rb []byte 94 nr int 95 lsa Sockaddr 96 ) 97 98 rb = make([]byte, Getpagesize()) 99 nr, _, e = Recvfrom(s, rb, 0) 100 if e != nil { 101 return nil, e 102 } 103 if nr < NLMSG_HDRLEN { 104 return nil, EINVAL 105 } 106 rb = rb[:nr] 107 tab = append(tab, rb...) 108 109 msgs, _ := ParseNetlinkMessage(rb) 110 for _, m := range msgs { 111 if lsa, e = Getsockname(s); e != nil { 112 return nil, e 113 } 114 switch v := lsa.(type) { 115 case *SockaddrNetlink: 116 if m.Header.Seq != uint32(seq) || m.Header.Pid != v.Pid { 117 return nil, EINVAL 118 } 119 default: 120 return nil, EINVAL 121 } 122 if m.Header.Type == NLMSG_DONE { 123 goto done 124 } 125 if m.Header.Type == NLMSG_ERROR { 126 return nil, EINVAL 127 } 128 } 129 } 130 131 done: 132 return tab, nil 133 } 134 135 // NetlinkMessage represents the netlink message. 136 type NetlinkMessage struct { 137 Header NlMsghdr 138 Data []byte 139 } 140 141 // ParseNetlinkMessage parses buf as netlink messages and returns 142 // the slice containing the NetlinkMessage structs. 143 func ParseNetlinkMessage(buf []byte) ([]NetlinkMessage, error) { 144 var ( 145 h *NlMsghdr 146 dbuf []byte 147 dlen int 148 e error 149 msgs []NetlinkMessage 150 ) 151 152 for len(buf) >= NLMSG_HDRLEN { 153 h, dbuf, dlen, e = netlinkMessageHeaderAndData(buf) 154 if e != nil { 155 break 156 } 157 m := NetlinkMessage{} 158 m.Header = *h 159 m.Data = dbuf[:h.Len-NLMSG_HDRLEN] 160 msgs = append(msgs, m) 161 buf = buf[dlen:] 162 } 163 164 return msgs, e 165 } 166 167 func netlinkMessageHeaderAndData(buf []byte) (*NlMsghdr, []byte, int, error) { 168 h := (*NlMsghdr)(unsafe.Pointer(&buf[0])) 169 if h.Len < NLMSG_HDRLEN || int(h.Len) > len(buf) { 170 return nil, nil, 0, EINVAL 171 } 172 return h, buf[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), nil 173 } 174 175 // NetlinkRouteAttr represents the netlink route attribute. 176 type NetlinkRouteAttr struct { 177 Attr RtAttr 178 Value []byte 179 } 180 181 // ParseNetlinkRouteAttr parses msg's payload as netlink route 182 // attributes and returns the slice containing the NetlinkRouteAttr 183 // structs. 184 func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, error) { 185 var ( 186 buf []byte 187 a *RtAttr 188 alen int 189 vbuf []byte 190 e error 191 attrs []NetlinkRouteAttr 192 ) 193 194 switch msg.Header.Type { 195 case RTM_NEWLINK, RTM_DELLINK: 196 buf = msg.Data[SizeofIfInfomsg:] 197 case RTM_NEWADDR, RTM_DELADDR: 198 buf = msg.Data[SizeofIfAddrmsg:] 199 case RTM_NEWROUTE, RTM_DELROUTE: 200 buf = msg.Data[SizeofRtMsg:] 201 default: 202 return nil, EINVAL 203 } 204 205 for len(buf) >= SizeofRtAttr { 206 a, vbuf, alen, e = netlinkRouteAttrAndValue(buf) 207 if e != nil { 208 break 209 } 210 ra := NetlinkRouteAttr{} 211 ra.Attr = *a 212 ra.Value = vbuf[:a.Len-SizeofRtAttr] 213 attrs = append(attrs, ra) 214 buf = buf[alen:] 215 } 216 217 return attrs, nil 218 } 219 220 func netlinkRouteAttrAndValue(buf []byte) (*RtAttr, []byte, int, error) { 221 h := (*RtAttr)(unsafe.Pointer(&buf[0])) 222 if h.Len < SizeofRtAttr || int(h.Len) > len(buf) { 223 return nil, nil, 0, EINVAL 224 } 225 return h, buf[SizeofRtAttr:], rtaAlignOf(int(h.Len)), nil 226 }