]>
Commit | Line | Data |
---|---|---|
1 | package Guardian::Socket; | |
2 | use strict; | |
3 | use warnings; | |
4 | ||
5 | use Exporter qw(import); | |
6 | ||
7 | our @EXPORT_OK = qw(Server Client Message_Parser RemoveSocketFile); | |
8 | ||
9 | use IO::Socket::UNIX qw( SOCK_STREAM SOMAXCONN ); | |
10 | ||
11 | # The path and filename to the UNIX socket. | |
12 | my $socketpath = "/run/guardian"; | |
13 | my $socketfile = "/run/guardian/guardian.sock"; | |
14 | ||
15 | # Hash with all supported socket commands and events which should | |
16 | # be returned by the parser. | |
17 | my %supported_commands = ( | |
18 | 'block' => 'block', | |
19 | 'unblock' => 'unblock', | |
20 | 'flush' => 'flush', | |
21 | 'reload' => 'reload', | |
22 | 'reload-ignore-list' => 'reload-ignore-list', | |
23 | 'logrotate' => 'logrotate', | |
24 | ); | |
25 | ||
26 | # | |
27 | ## Socket server function. | |
28 | # | |
29 | ## It is used to create the server component to provide an IPC | |
30 | ## mechanism for guardian. The server function creates an UNIX | |
31 | ## socket. | |
32 | # | |
33 | sub Server ($) { | |
34 | my $socket_owner = shift; | |
35 | ||
36 | # If the path for the socketfile does not exist, try to | |
37 | # create it. | |
38 | unless (-d "$socketpath") { | |
39 | mkdir("$socketpath") or die "Could not create $socketpath: $!"; | |
40 | } | |
41 | ||
42 | # Delete an existing socket file. | |
43 | if (-e "$socketfile") { | |
44 | unlink $socketfile | |
45 | or die "Could not release existing socket file: $!"; | |
46 | } | |
47 | ||
48 | # Create a new UNIX socket. | |
49 | my $server = IO::Socket::UNIX->new( | |
50 | Local => $socketfile, | |
51 | Listen => SOMAXCONN, | |
52 | Type => SOCK_STREAM, | |
53 | ) or die "Could not create socket: $!"; | |
54 | ||
55 | ||
56 | # Translate the given user/group name into ID values. | |
57 | if (defined ($socket_owner)) { | |
58 | # Splitt provided user/group into single arguments. | |
59 | my ($username, $groupname) = split(/:/, $socket_owner); | |
60 | ||
61 | # Get the ID for the given user name. | |
62 | my $uid = getpwnam($username) or die "Could not get an UID for $username: $!"; | |
63 | ||
64 | # Get the ID for given group name. | |
65 | my $gid = getgrnam($groupname) or die "Could not get a GID for $groupname: $!"; | |
66 | ||
67 | # Set new ownership for the socket file. | |
68 | chown($uid, $gid, "$socketfile") or die "Could not change ownership to ($uid:$gid) for $socketfile: $!"; | |
69 | } | |
70 | ||
71 | # Return the server object. | |
72 | return $server; | |
73 | } | |
74 | ||
75 | # | |
76 | ## A client for the socket server. | |
77 | # | |
78 | ## This function provides a simple client to connect to the server socket | |
79 | ## and send messages through it to a running guardian process. | |
80 | # | |
81 | sub Client($) { | |
82 | my ($message) = @_; | |
83 | ||
84 | # Create the client and connect to the server socket. | |
85 | my $client = IO::Socket::UNIX->new( | |
86 | Type => SOCK_STREAM, | |
87 | Peer => $socketfile, | |
88 | ) or die "Could not connect to socketfile: $!\n"; | |
89 | ||
90 | # Remove any newline. | |
91 | chomp($message); | |
92 | ||
93 | # Send the message through the socket. | |
94 | print $client "$message\n"; | |
95 | } | |
96 | ||
97 | # | |
98 | ## The Socket message parser. | |
99 | # | |
100 | ## This subfunction is responsible for parsing any data or messages | |
101 | ## which have been recieved through the server socket. | |
102 | # | |
103 | sub Message_Parser ($) { | |
104 | # Splitt the message into single parts. | |
105 | # The first part contains the command, the second | |
106 | # one an optional argument. | |
107 | my @message = split(/ /, $_[0]); | |
108 | my ($command, $optarg, $unsupported) = @message; | |
109 | ||
110 | # Currently only socket messages with two arguments (command and | |
111 | # the additional argument which is required for some commands) | |
112 | # are supported. If a third argument is passed, the message | |
113 | # is invalid and the parser returns false. | |
114 | if ($unsupported) { | |
115 | return undef; | |
116 | } | |
117 | ||
118 | # Check if we got a supported command. | |
119 | if (exists $supported_commands{$command}) { | |
120 | # Check an optional argument has been given. | |
121 | if ($optarg) { | |
122 | # The message is valid, return the event and | |
123 | # the optional argument. | |
124 | return "$supported_commands{$command} $optarg Socket User-requested action."; | |
125 | } else { | |
126 | # Only return the event for the recieved command. | |
127 | return "$supported_commands{$command}"; | |
128 | } | |
129 | } | |
130 | ||
131 | # If we got here, the command was not supported or something different | |
132 | # went wrong. In such cases the function will return undef (False). | |
133 | return undef; | |
134 | } | |
135 | ||
136 | # | |
137 | ## RemoveSocketFile function. | |
138 | # | |
139 | ## A tiny function which just removes an existing Socket file. | |
140 | # | |
141 | sub RemoveSocketFile () { | |
142 | # Check if a socketfile exists. | |
143 | if (-e $socketfile) { | |
144 | # Delete the socket file. | |
145 | unlink($socketfile); | |
146 | } | |
147 | } | |
148 | ||
149 | 1; |