-
Notifications
You must be signed in to change notification settings - Fork 0
/
utmp_linux.go
99 lines (88 loc) · 1.77 KB
/
utmp_linux.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package logon
import (
"bytes"
"encoding/binary"
"io"
"net"
"strconv"
"time"
)
const (
Empty = 0x0
RunLevel = 0x1
BootTime = 0x2
NewTime = 0x3
OldTime = 0x4
InitProcess = 0x5
LoginProcess = 0x6
UserProcess = 0x7
DeadProcess = 0x8
Accounting = 0x9
)
const (
LineSize = 32
NameSize = 32
HostSize = 256
)
// utmp structures
// see man utmp
type ExitStatus struct {
Termination int16
Exit int16
}
type TimeVal struct {
Sec int32
Usec int32
}
type Utmp struct {
Type int16
// alignment
_ [2]byte
Pid int32
Device [LineSize]byte
Id [4]byte
User [NameSize]byte
Host [HostSize]byte
Exit ExitStatus
Session int32
Time TimeVal
AddrV6 [16]byte
// Reserved member
Reserved [20]byte
}
// Addr returns the IPv4 or IPv6 address of the login record.
func (u *Utmp) Addr() net.IP {
ip := make(net.IP, 16)
// no error checking: reading from r.AddrV6 cannot fail
binary.Read(bytes.NewReader(u.AddrV6[:]), binary.BigEndian, ip)
if bytes.Equal(ip[4:], net.IPv6zero[4:]) {
// IPv4 address, shorten the slice so that net.IP behaves correctly:
ip = ip[:4]
}
return ip
}
func (u *Utmp) Event(class string) *Event {
tv := time.Unix(int64(u.Time.Sec), 0)
return &Event{
RecordID: uint64(tv.Unix()),
MinionID: xEnv.ID(),
Inet: xEnv.Inet(),
Device: string(u.Device[:trim(u.Device[:])]),
Host: string(u.Host[:trim(u.Host[:])]),
User: string(u.User[:trim(u.User[:])]),
Addr: u.Addr().String(),
Time: tv,
Class: class,
Pid: int32(u.Pid),
Typ: strconv.Itoa(int(u.Type)),
}
}
// read utmp
func readUtmp(file io.Reader) (*Utmp, error) {
u := new(Utmp)
err := binary.Read(file, binary.LittleEndian, u)
if err != nil {
return nil, err
}
return u, nil
}