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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
package nslcd_systemd
import (
"fmt"
"net"
"nslcd_proto"
"os"
"os/signal"
sd "sd_daemon"
"sd_daemon/logger"
"sd_daemon/lsb"
"sync"
"syscall"
)
type Backend interface {
nslcd_proto.Backend
Reload() error
}
func get_socket() (socket net.Listener, err error) {
socket = nil
err = nil
fds := sd.ListenFds(true)
if fds == nil {
err = fmt.Errorf("failed to aquire sockets from systemd")
return
}
if len(fds) != 1 {
err = fmt.Errorf("wrong number of sockets from systemd: expected %d but got %d", 1, len(fds))
return
}
socket, err = net.FileListener(fds[0])
fds[0].Close()
return
}
func getpeercred(conn *net.UnixConn) (cred nslcd_proto.Ucred, err error) {
file, err := conn.File()
if err != nil {
return
}
defer file.Close()
_cred, err := syscall.GetsockoptUcred(int(file.Fd()), syscall.SOL_SOCKET, syscall.SO_PEERCRED)
cred = nslcd_proto.Ucred(*_cred)
return
}
func handler(conn *net.UnixConn, backend nslcd_proto.Backend) {
defer conn.Close()
cred, err := getpeercred(conn)
if err != nil {
logger.Debug("connection from unknown client")
} else {
logger.Debug("connection from pid=%v uid=%v gid=%v",
cred.Pid, cred.Uid, cred.Gid)
}
err = nslcd_proto.HandleRequest(backend, conn, conn, cred)
if err != nil {
logger.Debug("Error while handling request: %v", err)
}
}
func Main(backend Backend) uint8 {
var err error = nil
var socket net.Listener = nil
defer func() {
if socket != nil {
socket.Close()
}
}()
disable_nss_module()
socket, err = get_socket()
if err != nil {
logger.Err("%s", err.Error())
sd.Notify(false, "STOPPING=1")
return lsb.EXIT_NOTRUNNING
}
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGTERM, syscall.SIGHUP)
sock := make(chan *net.UnixConn, 1)
go func() {
defer lsb.Recover()
for {
conn, err := socket.Accept()
if err != nil {
logger.Notice("Accept: %s", err.Error())
}
sock <- conn.(*net.UnixConn)
}
}()
exit := lsb.EXIT_SUCCESS
var wg sync.WaitGroup
sd.Notify(false, "READY=1")
Loop:
for {
select {
case sig := <-sigs:
switch sig {
case syscall.SIGTERM:
break Loop
case syscall.SIGHUP:
sd.Notify(false, "RELOADING=1")
err := backend.Reload()
if err != nil {
logger.Notice("Reload: %s", err.Error())
exit = lsb.EXIT_NOTRUNNING
break Loop
}
sd.Notify(false, "READY=1")
}
case conn := <-sock:
wg.Add(1)
go func() {
defer lsb.Recover()
defer wg.Done()
handler(conn, backend)
}()
}
}
sd.Notify(false, "STOPPING=1")
wg.Wait()
return exit
}
|