source: code/trunk/vendor/github.com/prometheus/procfs/net_unix.go@ 822

Last change on this file since 822 was 822, checked in by yakumo.izuru, 22 months ago

Prefer immortal.run over runit and rc.d, use vendored modules
for convenience.

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 5.9 KB
Line 
1// Copyright 2018 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package procfs
15
16import (
17 "bufio"
18 "fmt"
19 "io"
20 "os"
21 "strconv"
22 "strings"
23)
24
25// For the proc file format details,
26// see https://elixir.bootlin.com/linux/v4.17/source/net/unix/af_unix.c#L2815
27// and https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/net.h#L48.
28
29// Constants for the various /proc/net/unix enumerations.
30// TODO: match against x/sys/unix or similar?
31const (
32 netUnixTypeStream = 1
33 netUnixTypeDgram = 2
34 netUnixTypeSeqpacket = 5
35
36 netUnixFlagDefault = 0
37 netUnixFlagListen = 1 << 16
38
39 netUnixStateUnconnected = 1
40 netUnixStateConnecting = 2
41 netUnixStateConnected = 3
42 netUnixStateDisconnected = 4
43)
44
45// NetUNIXType is the type of the type field.
46type NetUNIXType uint64
47
48// NetUNIXFlags is the type of the flags field.
49type NetUNIXFlags uint64
50
51// NetUNIXState is the type of the state field.
52type NetUNIXState uint64
53
54// NetUNIXLine represents a line of /proc/net/unix.
55type NetUNIXLine struct {
56 KernelPtr string
57 RefCount uint64
58 Protocol uint64
59 Flags NetUNIXFlags
60 Type NetUNIXType
61 State NetUNIXState
62 Inode uint64
63 Path string
64}
65
66// NetUNIX holds the data read from /proc/net/unix.
67type NetUNIX struct {
68 Rows []*NetUNIXLine
69}
70
71// NetUNIX returns data read from /proc/net/unix.
72func (fs FS) NetUNIX() (*NetUNIX, error) {
73 return readNetUNIX(fs.proc.Path("net/unix"))
74}
75
76// readNetUNIX reads data in /proc/net/unix format from the specified file.
77func readNetUNIX(file string) (*NetUNIX, error) {
78 // This file could be quite large and a streaming read is desirable versus
79 // reading the entire contents at once.
80 f, err := os.Open(file)
81 if err != nil {
82 return nil, err
83 }
84 defer f.Close()
85
86 return parseNetUNIX(f)
87}
88
89// parseNetUNIX creates a NetUnix structure from the incoming stream.
90func parseNetUNIX(r io.Reader) (*NetUNIX, error) {
91 // Begin scanning by checking for the existence of Inode.
92 s := bufio.NewScanner(r)
93 s.Scan()
94
95 // From the man page of proc(5), it does not contain an Inode field,
96 // but in actually it exists. This code works for both cases.
97 hasInode := strings.Contains(s.Text(), "Inode")
98
99 // Expect a minimum number of fields, but Inode and Path are optional:
100 // Num RefCount Protocol Flags Type St Inode Path
101 minFields := 6
102 if hasInode {
103 minFields++
104 }
105
106 var nu NetUNIX
107 for s.Scan() {
108 line := s.Text()
109 item, err := nu.parseLine(line, hasInode, minFields)
110 if err != nil {
111 return nil, fmt.Errorf("failed to parse /proc/net/unix data %q: %w", line, err)
112 }
113
114 nu.Rows = append(nu.Rows, item)
115 }
116
117 if err := s.Err(); err != nil {
118 return nil, fmt.Errorf("failed to scan /proc/net/unix data: %w", err)
119 }
120
121 return &nu, nil
122}
123
124func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, error) {
125 fields := strings.Fields(line)
126
127 l := len(fields)
128 if l < min {
129 return nil, fmt.Errorf("expected at least %d fields but got %d", min, l)
130 }
131
132 // Field offsets are as follows:
133 // Num RefCount Protocol Flags Type St Inode Path
134
135 kernelPtr := strings.TrimSuffix(fields[0], ":")
136
137 users, err := u.parseUsers(fields[1])
138 if err != nil {
139 return nil, fmt.Errorf("failed to parse ref count %q: %w", fields[1], err)
140 }
141
142 flags, err := u.parseFlags(fields[3])
143 if err != nil {
144 return nil, fmt.Errorf("failed to parse flags %q: %w", fields[3], err)
145 }
146
147 typ, err := u.parseType(fields[4])
148 if err != nil {
149 return nil, fmt.Errorf("failed to parse type %q: %w", fields[4], err)
150 }
151
152 state, err := u.parseState(fields[5])
153 if err != nil {
154 return nil, fmt.Errorf("failed to parse state %q: %w", fields[5], err)
155 }
156
157 var inode uint64
158 if hasInode {
159 inode, err = u.parseInode(fields[6])
160 if err != nil {
161 return nil, fmt.Errorf("failed to parse inode %q: %w", fields[6], err)
162 }
163 }
164
165 n := &NetUNIXLine{
166 KernelPtr: kernelPtr,
167 RefCount: users,
168 Type: typ,
169 Flags: flags,
170 State: state,
171 Inode: inode,
172 }
173
174 // Path field is optional.
175 if l > min {
176 // Path occurs at either index 6 or 7 depending on whether inode is
177 // already present.
178 pathIdx := 7
179 if !hasInode {
180 pathIdx--
181 }
182
183 n.Path = fields[pathIdx]
184 }
185
186 return n, nil
187}
188
189func (u NetUNIX) parseUsers(s string) (uint64, error) {
190 return strconv.ParseUint(s, 16, 32)
191}
192
193func (u NetUNIX) parseType(s string) (NetUNIXType, error) {
194 typ, err := strconv.ParseUint(s, 16, 16)
195 if err != nil {
196 return 0, err
197 }
198
199 return NetUNIXType(typ), nil
200}
201
202func (u NetUNIX) parseFlags(s string) (NetUNIXFlags, error) {
203 flags, err := strconv.ParseUint(s, 16, 32)
204 if err != nil {
205 return 0, err
206 }
207
208 return NetUNIXFlags(flags), nil
209}
210
211func (u NetUNIX) parseState(s string) (NetUNIXState, error) {
212 st, err := strconv.ParseInt(s, 16, 8)
213 if err != nil {
214 return 0, err
215 }
216
217 return NetUNIXState(st), nil
218}
219
220func (u NetUNIX) parseInode(s string) (uint64, error) {
221 return strconv.ParseUint(s, 10, 64)
222}
223
224func (t NetUNIXType) String() string {
225 switch t {
226 case netUnixTypeStream:
227 return "stream"
228 case netUnixTypeDgram:
229 return "dgram"
230 case netUnixTypeSeqpacket:
231 return "seqpacket"
232 }
233 return "unknown"
234}
235
236func (f NetUNIXFlags) String() string {
237 switch f {
238 case netUnixFlagListen:
239 return "listen"
240 default:
241 return "default"
242 }
243}
244
245func (s NetUNIXState) String() string {
246 switch s {
247 case netUnixStateUnconnected:
248 return "unconnected"
249 case netUnixStateConnecting:
250 return "connecting"
251 case netUnixStateConnected:
252 return "connected"
253 case netUnixStateDisconnected:
254 return "disconnected"
255 }
256 return "unknown"
257}
Note: See TracBrowser for help on using the repository browser.