]> git.ozlabs.org Git - petitboot/blob - discover/user-event.c
013357b49bff6340f671af561d0cb25ec12a18fc
[petitboot] / discover / user-event.c
1 /*
2  *  Copyright (C) 2009 Sony Computer Entertainment Inc.
3  *  Copyright 2009 Sony Corp.
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; version 2 of the License.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #if defined(HAVE_CONFIG_H)
20 #include "config.h"
21 #endif
22
23 #define _GNU_SOURCE
24 #include <assert.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <sys/socket.h>
28 #include <sys/types.h>
29 #include <sys/un.h>
30
31 #include <log/log.h>
32 #include <talloc/talloc.h>
33 #include <waiter/waiter.h>
34
35 #include "device-handler.h"
36 #include "event.h"
37 #include "user-event.h"
38
39
40 struct user_event {
41         struct device_handler *handler;
42         int socket;
43 };
44
45 static const char *event_action_name(enum event_action action)
46 {
47         switch (action) {
48         case EVENT_ACTION_ADD:
49                 return "add";
50         case EVENT_ACTION_REMOVE:
51                 return "remove";
52         case EVENT_ACTION_CONF:
53                 return "conf";
54         default:
55                 break;
56         }
57
58         return "unknown";
59 }
60
61 static void user_event_print_event(struct event __attribute__((unused)) *event)
62 {
63         int i;
64
65         pb_log("user_event %s event:\n", event_action_name(event->action));
66         pb_log("\tdevice: %s\n", event->device);
67
68         for (i = 0; i < event->n_params; i++)
69                 pb_log("\t%-12s => %s\n",
70                         event->params[i].name, event->params[i].value);
71 }
72
73 static void user_event_handle_message(struct user_event *uev, char *buf,
74         int len)
75 {
76         int result;
77         struct event *event;
78
79         event = talloc(uev, struct event);
80         event->type = EVENT_TYPE_USER;
81
82         result = event_parse_ad_message(event, buf, len);
83
84         if (result)
85                 return;
86
87         user_event_print_event(event);
88         device_handler_event(uev->handler, event);
89         talloc_free(event);
90
91         return;
92 }
93
94 static int user_event_process(void *arg)
95 {
96         struct user_event *uev = arg;
97         char buf[PBOOT_USER_EVENT_SIZE];
98         int len;
99
100         len = recvfrom(uev->socket, buf, sizeof(buf), 0, NULL, NULL);
101
102         if (len < 0) {
103                 pb_log("%s: socket read failed: %s", __func__, strerror(errno));
104                 return 0;
105         }
106
107         if (len == 0) {
108                 pb_log("%s: empty", __func__);
109                 return 0;
110         }
111
112         pb_log("%s: %u bytes\n", __func__, len);
113
114         user_event_handle_message(uev, buf, len);
115
116         return 0;
117 }
118
119 static int user_event_destructor(void *arg)
120 {
121         struct user_event *uev = arg;
122
123         pb_log("%s\n", __func__);
124
125         if (uev->socket >= 0)
126                 close(uev->socket);
127
128         return 0;
129 }
130
131 struct user_event *user_event_init(struct waitset *waitset,
132                 struct device_handler *handler)
133 {
134         struct sockaddr_un addr;
135         struct user_event *uev;
136
137         unlink(PBOOT_USER_EVENT_SOCKET);
138
139         uev = talloc(NULL, struct user_event);
140
141         uev->handler = handler;
142
143         uev->socket = socket(AF_UNIX, SOCK_DGRAM, 0);
144         if (uev->socket < 0) {
145                 pb_log("%s: Error creating event handler socket: %s\n",
146                         __func__, strerror(errno));
147                 goto out_err;
148         }
149
150         talloc_set_destructor(uev, user_event_destructor);
151
152         memset(&addr, 0, sizeof(addr));
153         addr.sun_family = AF_UNIX;
154         strcpy(addr.sun_path, PBOOT_USER_EVENT_SOCKET);
155
156         if (bind(uev->socket, (struct sockaddr *)&addr, sizeof(addr))) {
157                 pb_log("Error binding event handler socket: %s\n",
158                         strerror(errno));
159         }
160
161         waiter_register_io(waitset, uev->socket, WAIT_IN,
162                         user_event_process, uev);
163
164         pb_log("%s: waiting on %s\n", __func__, PBOOT_USER_EVENT_SOCKET);
165
166         return uev;
167
168 out_err:
169         talloc_free(uev);
170         return NULL;
171 }
172
173 /**
174  * user_event_trigger - Trigger known user events
175  *
176  * SIGUSR1 causes udhcpc to renew the current lease or obtain a new lease.
177  */
178
179 void user_event_trigger(struct user_event __attribute__((unused)) *uev)
180 {
181         /* FIXME: todo */
182 }
183
184 void user_event_destroy(struct user_event *uev)
185 {
186         talloc_free(uev);
187 }