1 /*
2  * $Id$
3  *
4  * Copyright (c) 2008, 2009
5  *      Sten Spans <sten@blinkenlights.nl>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #ifndef _common_h
21 #define _common_h
22 
23 #include "config.h"
24 #include <stdarg.h>
25 #include <stddef.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <inttypes.h>
29 #include <limits.h>
30 #include <string.h>
31 #ifndef S_SPLINT_S
32 #include <unistd.h>
33 #endif
34 #include <fcntl.h>
35 #include <signal.h>
36 #include <time.h>
37 #include <errno.h>
38 #include <assert.h>
39 #if defined(HAVE_STRNVIS) && !defined(BROKEN_STRNVIS)
40 #include <vis.h>
41 #endif
42 #if HAVE_NETINET_IN_H
43 #include <netinet/in.h>
44 #endif
45 #include <arpa/inet.h>
46 #include <sys/types.h>
47 #include <sys/socket.h>
48 #include <sys/utsname.h>
49 #include <sys/ioctl.h>
50 #if HAVE_SYS_SYSCTL_H
51 #include <sys/param.h>
52 #include <sys/sysctl.h>
53 #endif
54 #include <sys/stat.h>
55 #include <sys/time.h>
56 #include <sys/uio.h>
57 #include <pwd.h>
58 
59 #include <event.h>
60 #if HAVE_EVHTTP_H
61 #include <evhttp.h>
62 #endif /* HAVE_EVHTTP_H */
63 
64 #if HAVE_NET_IF_H
65 #include <net/if.h>
66 #define _LINUX_IF_H
67 #define IFF_LOWER_UP 0x10000
68 #endif
69 #if HAVE_NETINET_IF_ETHER_H
70 #include <netinet/if_ether.h>
71 #endif
72 
73 #ifndef __noreturn
74 # define __noreturn	__attribute__ ((noreturn))
75 #endif
76 #ifndef __packed
77 # define __packed	__attribute__ ((packed))
78 #endif
79 #ifndef __nonnull
80 # define __nonnull(x)	__attribute__ ((__nonnull__ x))
81 #endif
82 #ifndef __unused
83 #  define __unused(x)	__attribute__((__unused__)) x
84 #endif
85 #if __GNUC__ >= 3
86 # define likely(x)	__builtin_expect (!!(x), 1)
87 # define unlikely(x)	__builtin_expect (!!(x), 0)
88 #else
89 # define likely(x)	(x)
90 # define unlikely(x)	(x)
91 #endif
92 
93 #include "ether.h"
94 #include "compat/compat.h"
95 
96 #define SLEEPTIME   30
97 #define LADVD_TTL   180
98 
99 #ifndef IFDESCRSIZE
100 #define IFDESCRSIZE 64
101 #endif
102 
103 #define LLDP_INVENTORY_SIZE 32
104 
105 #define NETIF_BONDING_LACP  	1
106 #define NETIF_BONDING_FAILOVER	2
107 #define NETIF_BONDING_OTHER	3
108 #define NETIF_CHILD_ACTIVE	1
109 #define NETIF_CHILD_BACKUP	2
110 
111 #define NETIF_INDEX_MAX		UINT32_MAX
112 
113 struct netif {
114     uint32_t index;
115     char name[IFNAMSIZ];
116     char description[IFDESCRSIZE];
117     uint8_t hwaddr[ETHER_ADDR_LEN];
118     uint16_t mtu;
119     int8_t duplex;
120     int8_t autoneg_supported;
121     int8_t autoneg_enabled;
122     uint16_t autoneg_pmd;
123     uint16_t mau;
124 
125     uint32_t ipaddr4;
126     uint32_t ipaddr6[4];
127 
128     uint8_t argv;
129     int8_t type;
130     uint8_t child;
131     uint8_t bonding_mode;
132     uint8_t lacp_index;
133 
134     uint16_t vlan_id;
135     uint32_t vlan_parent;
136 
137     uint8_t protos;
138     uint8_t update;
139 
140     struct netif *parent;
141     struct netif *subif;
142 
143     // should be last
144     TAILQ_ENTRY(netif) entries;
145 
146     uint8_t link_event;
147     uint8_t device_identified;
148     char device_name[IFDESCRSIZE];
149 };
150 
151 TAILQ_HEAD(nhead, netif);
152 
153 struct exclif {
154     char name[IFNAMSIZ];
155     TAILQ_ENTRY(exclif) entries;
156 };
157 
158 TAILQ_HEAD(ehead, exclif);
159 
160 struct hinv {
161     char hw_revision[LLDP_INVENTORY_SIZE + 1];
162     char fw_revision[LLDP_INVENTORY_SIZE + 1];
163     char sw_revision[LLDP_INVENTORY_SIZE + 1];
164     char serial_number[LLDP_INVENTORY_SIZE + 1];
165     char manufacturer[LLDP_INVENTORY_SIZE + 1];
166     char model_name[LLDP_INVENTORY_SIZE + 1];
167     char asset_id[LLDP_INVENTORY_SIZE + 1];
168 };
169 
170 struct my_sysinfo {
171     struct utsname uts;
172     char uts_str[256];
173     uint8_t uts_rel[3];
174     char platform[256];
175     char hostname[256];
176     char country[3];
177     char location[256];
178     uint16_t cap;
179     uint16_t cap_active;
180     uint16_t cap_lldpmed;
181     int8_t lldpmed_devtype;
182     uint8_t hwaddr[ETHER_ADDR_LEN];
183     uint16_t physif_count;
184 
185     uint32_t maddr4;
186     uint32_t maddr6[4];
187     const char *mifname;
188     struct netif *mnetif;
189 
190     struct hinv hinv;
191 };
192 
193 #define CAP_REPEATER	(1 << 0)
194 #define CAP_BRIDGE	(1 << 1)
195 #define CAP_HOST	(1 << 2)
196 #define CAP_ROUTER	(1 << 3)
197 #define CAP_SWITCH	(1 << 4)
198 #define CAP_WLAN	(1 << 5)
199 #define CAP_DOCSIS	(1 << 6)
200 #define CAP_PHONE	(1 << 7)
201 #define CAP_OTHER	(1 << 8)
202 #define CAP_MAX		9
203 #define CAP_STRING	"rBHRSWCTO"
204 
205 #define NETIF_INVALID	INT8_MIN
206 #define NETIF_VLAN	-1
207 #define NETIF_REGULAR	0
208 #define NETIF_WIRELESS	1
209 #define NETIF_TAP	2
210 #define NETIF_PARENT	10
211 #define NETIF_TEAMING	11
212 #define NETIF_BONDING	12
213 #define NETIF_BRIDGE	13
214 #define NETIF_OLD	INT8_MAX
215 
216 #define OPT_DAEMON	(1 << 0)
217 #define OPT_SEND	(1 << 1)
218 #define OPT_RECV	(1 << 2)
219 #define OPT_AUTO	(1 << 3)
220 #define OPT_ONCE	(1 << 4)
221 #define OPT_ARGV	(1 << 5)
222 #define OPT_DEBUG	(1 << 6)
223 #define OPT_MNETIF	(1 << 7)
224 #define OPT_MADDR	(1 << 8)
225 #define OPT_WIRELESS	(1 << 9)
226 #define OPT_TAP		(1 << 10)
227 #define OPT_IFDESCR	(1 << 11)
228 #define OPT_USEDESCR	(1 << 12)
229 #define OPT_CHASSIS_IF	(1 << 13)
230 #define OPT_CHECK	(1 << 31)
231 
232 extern uint32_t options;
233 
234 struct parent_req {
235     uint8_t op;
236     uint32_t index;
237     char name[IFNAMSIZ];
238     ssize_t len;
239     char buf[512];
240 };
241 
242 #define TEAM_NETIF_CNT 32
243 struct parent_team_info {
244     uint8_t mode;
245     uint8_t cnt;
246     uint32_t netifs[TEAM_NETIF_CNT];
247     uint32_t netif_active;
248 };
249 
250 #define PARENT_REQ_MIN	    offsetof(struct parent_req, buf)
251 #define PARENT_REQ_MAX	    sizeof(struct parent_req)
252 #define PARENT_REQ_LEN(l)   PARENT_REQ_MIN + l
253 
254 #define DECODE_STR	1
255 #define DECODE_PRINT	2
256 
257 #define PEER_HOSTNAME	0
258 #define PEER_PORTNAME	1
259 #define PEER_PORTDESCR	2
260 #define PEER_CAP	3
261 #define PEER_ADDR_INET4	4
262 #define PEER_ADDR_INET6	5
263 #define PEER_ADDR_802	6
264 #define PEER_VLAN_ID	7
265 #define PEER_MAX	8
266 #define PEER_STR(x,y)  ((x)?(free(y)):(x = y))
267 
268 static inline
peer_free(char * p[])269 void peer_free(char *p[]) {
270     int s;
271     for (s = 0; s < PEER_MAX; s++) {
272 	if (!p[s])
273 	    continue;
274 	free(p[s]);
275 	p[s] = NULL;
276     }
277 }
278 
279 struct parent_msg {
280     uint32_t index;
281     char name[IFNAMSIZ];
282     uint8_t proto;
283     time_t received;
284     ssize_t len;
285     unsigned char msg[ETHER_MAX_LEN];
286 
287     uint8_t decode;
288     uint16_t ttl;
289     char *peer[PEER_MAX];
290 
291     uint8_t lock;
292 
293     // should be last
294     TAILQ_ENTRY(parent_msg) entries;
295 };
296 
297 TAILQ_HEAD(mhead, parent_msg);
298 
299 #define PARENT_MSG_MIN	    offsetof(struct parent_msg, msg)
300 #define PARENT_MSG_MAX	    offsetof(struct parent_msg, decode)
301 #define PARENT_MSG_SIZ	    sizeof(struct parent_msg)
302 #define PARENT_MSG_LEN(l)   PARENT_MSG_MIN + l
303 #define PARENT_OPEN	    0
304 #define PARENT_CLOSE	    1
305 #define PARENT_DESCR	    2
306 #define PARENT_ALIAS	    3
307 #define PARENT_DEVICE	    4
308 #define PARENT_DEVICE_ID    5
309 #define PARENT_ETHTOOL_GSET 6
310 #define PARENT_ETHTOOL_GDRV 7
311 #define PARENT_TEAMNL	    8
312 #define PARENT_MAX	    9
313 
314 struct proto {
315     uint8_t enabled;
316     const char *name;
317     uint8_t dst_addr[ETHER_ADDR_LEN];
318     uint8_t llc_org[3];
319     uint16_t llc_pid;
320     size_t (* const build) (uint8_t, void *, struct netif *, struct nhead *,
321 			    struct my_sysinfo *);
322     unsigned char * (* const check) (void *, size_t);
323     size_t (* const decode) (struct parent_msg *);
324 };
325 
326 void cli_main(int argc, char *argv[]) __noreturn;
327 void child_init(int reqfd, int msgfd, int ifc, char *ifl[], struct passwd *pwd);
328 void parent_init(int reqfd, int msgfd, pid_t pid);
329 void parent_signal(int fd, short event, void *pid);
330 
331 void sysinfo_fetch(struct my_sysinfo *);
332 void netif_init();
333 uint16_t netif_fetch(int ifc, char *ifl[], struct my_sysinfo *, struct nhead *);
334 int netif_media(struct netif *);
335 
336 #endif /* _common_h */
337