1be19eb2a052bd79333c379cfa2d9d3fa5a0248e
[petitboot] / discover / event.c
1 #if defined(HAVE_CONFIG_H)
2 #include "config.h"
3 #endif
4
5 #include <string.h>
6
7 #include <log/log.h>
8 #include <talloc/talloc.h>
9
10 #include "event.h"
11
12 #define streq(a, b) (!strcasecmp((a), (b)))
13
14 /**
15  * event_parse_ad_header - Parse an <action>@<device> event header.
16  *
17  * The buffer is modified in place.
18  * Returns zero on success.
19  */
20
21 static int event_parse_ad_header(char *buf, int len, enum event_action *action,
22         char **device)
23 {
24         int headerlen;
25         char *sep;
26
27         *action = 0;
28         *device = NULL;
29         headerlen = strnlen(buf, len);
30
31         if (!headerlen) {
32                 pb_log("%s: bad header, no data\n", __func__);
33                 return -1;
34         }
35
36         /* we should see an <action>@<device>\0 at the head of the buffer */
37         sep = strchr(buf, '@');
38         if (!sep) {
39                 pb_log("%s: bad header: %s\n", __func__, buf);
40                 return -1;
41         }
42
43         /* terminate the action string */
44         *sep = '\0';
45
46         if (streq(buf, "add"))
47                 *action = EVENT_ACTION_ADD;
48         else if (streq(buf, "remove"))
49                 *action = EVENT_ACTION_REMOVE;
50         else if (streq(buf, "url"))
51                 *action = EVENT_ACTION_URL;
52         else if (streq(buf, "dhcp"))
53                 *action = EVENT_ACTION_DHCP;
54         else if (streq(buf, "boot"))
55                 *action = EVENT_ACTION_BOOT;
56         else if (streq(buf, "sync"))
57                 *action = EVENT_ACTION_SYNC;
58         else {
59                 pb_log("%s: unknown action: %s\n", __func__, buf);
60                 return -1;
61         }
62
63         if (!*(sep + 1)) {
64                 pb_log("%s: bad device: %s\n", __func__, buf);
65                 return -1;
66         }
67
68         *device = sep + 1;
69         return headerlen;
70 }
71
72 /**
73  * event_parse_params - Parse a <name>=<value> buffer.
74  *
75  * The buffer is not modified.
76  */
77
78 static void event_parse_params(struct event *event, const char *buf, int len)
79 {
80         int param_len, name_len, value_len;
81         struct param *param;
82         char *sep;
83
84         for (; len > 0; len -= param_len + 1, buf += param_len + 1) {
85
86                 /* find the length of the whole parameter */
87                 param_len = strnlen(buf, len);
88                 if (!param_len) {
89                         /* multiple NULs? skip over */
90                         param_len = 1;
91                         continue;
92                 }
93
94                 /* update the params array */
95                 event->params = talloc_realloc(event, event->params,
96                                         struct param, ++event->n_params);
97                 param = &event->params[event->n_params - 1];
98
99                 sep = memchr(buf, '=', param_len);
100                 if (!sep) {
101                         name_len = param_len;
102                         value_len = 0;
103                         param->value = "";
104                 } else {
105                         name_len = sep - buf;
106                         value_len = param_len - name_len - 1;
107                         param->value = talloc_strndup(event, sep + 1,
108                                         value_len);
109                 }
110                 param->name = talloc_strndup(event, buf, name_len);
111         }
112 }
113
114 int event_parse_ad_message(struct event *event, char *buf, int len)
115 {
116         enum event_action action;
117         int headerlen;
118         char *device;
119
120         headerlen = event_parse_ad_header(buf, len, &action, &device);
121
122         if (headerlen <= 0)
123                 return -1;
124
125         /* now we have an action and a device, we can construct the event */
126         event->action = action;
127         event->device = talloc_strdup(event, device);
128         event->n_params = 0;
129         event->params = NULL;
130
131         len -= headerlen + 1;
132         buf += headerlen + 1;
133         event_parse_params(event, buf, len);
134
135         return 0;
136 }
137
138 const char *event_get_param(const struct event *event, const char *name)
139 {
140         int i;
141
142         for (i = 0; i < event->n_params; i++)
143                 if (!strcasecmp(event->params[i].name, name))
144                         return event->params[i].value;
145
146         return NULL;
147 }
148
149 void event_set_param(struct event *event, const char *name, const char *value)
150 {
151         struct param *param;
152         int i;
153
154         /* if it's already present, replace the value of the old param */
155         for (i = 0; i < event->n_params; i++) {
156                 param = &event->params[i];
157                 if (!strcasecmp(param->name, name)) {
158                         talloc_free(param->value);
159                         param->value = talloc_strdup(event, value);
160                         return;
161                 }
162         }
163
164         /* not found - create a new param */
165         event->params = talloc_realloc(event, event->params,
166                                 struct param, ++event->n_params);
167         param = &event->params[event->n_params - 1];
168
169         param->name = talloc_strdup(event, name);
170         param->value = talloc_strdup(event, value);
171 }