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