github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/socket/netlink/provider.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package netlink 16 17 import ( 18 "fmt" 19 20 "github.com/SagerNet/gvisor/pkg/abi/linux" 21 "github.com/SagerNet/gvisor/pkg/context" 22 "github.com/SagerNet/gvisor/pkg/sentry/fs" 23 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 24 "github.com/SagerNet/gvisor/pkg/sentry/socket" 25 "github.com/SagerNet/gvisor/pkg/syserr" 26 ) 27 28 // Protocol is the implementation of a netlink socket protocol. 29 type Protocol interface { 30 // Protocol returns the Linux netlink protocol value. 31 Protocol() int 32 33 // CanSend returns true if this protocol may ever send messages. 34 // 35 // TODO(github.com/SagerNet/issue/1119): This is a workaround to allow 36 // advertising support for otherwise unimplemented features on sockets 37 // that will never send messages, thus making those features no-ops. 38 CanSend() bool 39 40 // ProcessMessage processes a single message from userspace. 41 // 42 // If err == nil, any messages added to ms will be sent back to the 43 // other end of the socket. Setting ms.Multi will cause an NLMSG_DONE 44 // message to be sent even if ms contains no messages. 45 ProcessMessage(ctx context.Context, msg *Message, ms *MessageSet) *syserr.Error 46 } 47 48 // Provider is a function that creates a new Protocol for a specific netlink 49 // protocol. 50 // 51 // Note that this is distinct from socket.Provider, which is used for all 52 // socket families. 53 type Provider func(t *kernel.Task) (Protocol, *syserr.Error) 54 55 // protocols holds a map of all known address protocols and their provider. 56 var protocols = make(map[int]Provider) 57 58 // RegisterProvider registers the provider of a given address protocol so that 59 // netlink sockets of that type can be created via socket(2). 60 // 61 // Preconditions: May only be called before any netlink sockets are created. 62 func RegisterProvider(protocol int, provider Provider) { 63 if p, ok := protocols[protocol]; ok { 64 panic(fmt.Sprintf("Netlink protocol %d already provided by %+v", protocol, p)) 65 } 66 67 protocols[protocol] = provider 68 } 69 70 // LINT.IfChange 71 72 // socketProvider implements socket.Provider. 73 type socketProvider struct { 74 } 75 76 // Socket implements socket.Provider.Socket. 77 func (*socketProvider) Socket(t *kernel.Task, stype linux.SockType, protocol int) (*fs.File, *syserr.Error) { 78 // Netlink sockets must be specified as datagram or raw, but they 79 // behave the same regardless of type. 80 if stype != linux.SOCK_DGRAM && stype != linux.SOCK_RAW { 81 return nil, syserr.ErrSocketNotSupported 82 } 83 84 provider, ok := protocols[protocol] 85 if !ok { 86 return nil, syserr.ErrProtocolNotSupported 87 } 88 89 p, err := provider(t) 90 if err != nil { 91 return nil, err 92 } 93 94 s, err := NewSocket(t, stype, p) 95 if err != nil { 96 return nil, err 97 } 98 99 d := socket.NewDirent(t, netlinkSocketDevice) 100 defer d.DecRef(t) 101 return fs.NewFile(t, d, fs.FileFlags{Read: true, Write: true, NonSeekable: true}, s), nil 102 } 103 104 // Pair implements socket.Provider.Pair by returning an error. 105 func (*socketProvider) Pair(*kernel.Task, linux.SockType, int) (*fs.File, *fs.File, *syserr.Error) { 106 // Netlink sockets never supports creating socket pairs. 107 return nil, nil, syserr.ErrNotSupported 108 } 109 110 // LINT.ThenChange(./provider_vfs2.go) 111 112 // init registers the socket provider. 113 func init() { 114 socket.RegisterProvider(linux.AF_NETLINK, &socketProvider{}) 115 socket.RegisterProviderVFS2(linux.AF_NETLINK, &socketProviderVFS2{}) 116 }