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