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 #include "config.h"
21 #include <check.h>
22 #include <paths.h>
23 #include <pcap.h>
24 
25 #include "common.h"
26 #include "util.h"
27 #include "proto/protos.h"
28 #include "main.h"
29 #include "check_wrap.h"
30 
31 uint32_t options = OPT_DAEMON | OPT_CHECK;
32 
START_TEST(test_my)33 START_TEST(test_my) {
34     char *ptr = NULL;
35     int s = -1, spair[2];
36     const char *errstr = NULL;
37     char buf[1024], *bp = NULL;
38     ssize_t len = 0;
39     size_t left;
40 
41     mark_point();
42     loglevel = INFO;
43     errstr = "empty";
44     my_log(CRIT, errstr);
45     my_log(DEBUG, "0123456789");
46     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
47 	"incorrect message logged: %s", check_wrap_errstr);
48 
49     mark_point();
50     loglevel = DEBUG;
51     errstr = "0123456789";
52     my_log(INFO, errstr);
53     fail_unless (strcmp(check_wrap_errstr, errstr) == 0, "message not logged");
54 
55     mark_point();
56     s = dup(STDERR_FILENO);
57     close(STDERR_FILENO);
58     my_socketpair(spair);
59     my_nonblock(spair[1]);
60     options &= ~OPT_DAEMON;
61     errstr = "test_my: debug\n";
62     memset(buf, 0, 1024);
63     my_log(INFO, "debug");
64     fflush(stderr);
65 
66     bp = buf;
67     left = 1024;
68     while (left > 0) {
69 	len = read(spair[1], bp, left);
70 	if (len <= 0)
71 	    break;
72 	left -= len;
73 	bp += len;
74     }
75     fail_unless(strcmp(buf, errstr) == 0, "invalid output: %s", buf);
76     options |= OPT_DAEMON;
77     close(spair[0]);
78     fail_if(dup(s) != STDERR_FILENO, "dup should re-create stderr");
79     close(s);
80     close(spair[1]);
81 
82     mark_point();
83     WRAP_FATAL_START();
84     my_fatal("error");
85     WRAP_FATAL_END();
86     fail_unless (strcmp(check_wrap_errstr, "error") == 0,
87 	"error not logged");
88 
89     mark_point();
90     ptr = my_malloc(100);
91     fail_unless (ptr != NULL, "a valid pointer should be returned");
92     free(ptr);
93     ptr = NULL;
94 
95     mark_point();
96     ptr = my_calloc(10, 10);
97     fail_unless (ptr != NULL, "a valid pointer should be returned");
98     free(ptr);
99     ptr = NULL;
100 
101     check_wrap_fail |= FAIL_CALLOC;
102     WRAP_FATAL_START();
103     ptr = my_calloc(10, 10);
104     WRAP_FATAL_END();
105     check_wrap_fail &= ~FAIL_CALLOC;
106     fail_unless (strcmp(check_wrap_errstr, "calloc failed") == 0,
107 	"error not logged");
108 
109     mark_point();
110     ptr = my_strdup("foo");
111     fail_unless (ptr != NULL, "a valid pointer should be returned");
112     free(ptr);
113     ptr = NULL;
114 
115     check_wrap_fail |= FAIL_STRDUP;
116     WRAP_FATAL_START();
117     ptr = my_strdup("bar");
118     WRAP_FATAL_END();
119     check_wrap_fail &= ~FAIL_STRDUP;
120     fail_unless (strcmp(check_wrap_errstr, "strdup failed") == 0,
121 	"error not logged");
122 
123     // skip the socket tests if there is no networking
124     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
125 	return;
126     close(s);
127 
128     mark_point();
129     s = my_socket(AF_INET, SOCK_DGRAM, 0);
130     fail_unless (s != -1, "a valid socket should be returned");
131     close(s);
132     s = 0;
133 
134     errstr = "opening socket failed";
135     WRAP_FATAL_START();
136     s = my_socket(AF_MAX, 0, 0);
137     WRAP_FATAL_END();
138     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
139 	"incorrect message logged: %s", check_wrap_errstr);
140 }
141 END_TEST
142 
START_TEST(test_my_mreq)143 START_TEST(test_my_mreq) {
144     struct parent_req mreq = {};
145     int spair[2];
146     extern int msock;
147     size_t ret;
148     const char *errstr = NULL;
149 
150     loglevel = INFO;
151     my_socketpair(spair);
152 
153     mark_point();
154     msock = -1;
155     errstr = "only -1 bytes written";
156     WRAP_FATAL_START();
157     my_mreq(&mreq);
158     WRAP_FATAL_END();
159     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
160 	"incorrect message logged: %s", check_wrap_errstr);
161 
162     mark_point();
163     msock = spair[1];
164     errstr = "check";
165     my_log(CRIT, errstr);
166     mreq.len = ETHER_MIN_LEN;
167     WRAP_WRITE(spair[0], &mreq, PARENT_REQ_LEN(mreq.len));
168     ret = my_mreq(&mreq);
169     fail_unless (ret == ETHER_MIN_LEN,
170 	"incorrect size %lu returned from my_mreq", ret);
171 
172     mark_point();
173     errstr = "invalid reply received from parent";
174     WRAP_WRITE(spair[0], &mreq, ETHER_MIN_LEN);
175     WRAP_FATAL_START();
176     my_mreq(&mreq);
177     WRAP_FATAL_END();
178     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
179 	"incorrect message logged: %s", check_wrap_errstr);
180 
181     close(spair[0]);
182     close(spair[1]);
183 }
184 END_TEST
185 
START_TEST(test_netif)186 START_TEST(test_netif) {
187     struct nhead nqueue;
188     struct nhead *netifs = &nqueue;
189     struct netif tnetifs[6];
190     struct netif *netif = NULL, *subif = NULL;
191     struct mhead mqueue;
192     struct parent_msg *msg = NULL, *nmsg = NULL;
193     struct parent_req *mreq = NULL;
194     char *descr = NULL;
195     int spair[2];
196     ssize_t len;
197     extern int msock;
198 
199     TAILQ_INIT(&nqueue);
200     TAILQ_INIT(&mqueue);
201     my_socketpair(spair);
202 
203     tnetifs[0].index = 0;
204     tnetifs[0].argv = 0;
205     tnetifs[0].child = 0;
206     tnetifs[0].type = NETIF_BONDING;
207     tnetifs[0].subif = &tnetifs[1];
208     strlcpy(tnetifs[0].name, "bond0", IFNAMSIZ);
209     strlcpy(tnetifs[0].description, "bond0", IFDESCRSIZE);
210 
211     tnetifs[1].index = 1;
212     tnetifs[1].argv = 1;
213     tnetifs[1].child = 1;
214     tnetifs[1].type = NETIF_REGULAR;
215     tnetifs[1].subif = &tnetifs[2];
216     strlcpy(tnetifs[1].name, "eth0", IFNAMSIZ);
217     strlcpy(tnetifs[1].description, "eth0", IFDESCRSIZE);
218 
219     tnetifs[2].index = 2;
220     tnetifs[2].argv = 0;
221     tnetifs[2].child = 1;
222     tnetifs[2].type = NETIF_REGULAR;
223     tnetifs[2].subif = NULL,
224     strlcpy(tnetifs[2].name, "eth2", IFNAMSIZ);
225     strlcpy(tnetifs[2].description, "eth2", IFDESCRSIZE);
226 
227     tnetifs[3].index = 4;
228     tnetifs[3].argv = 0;
229     tnetifs[3].child = 0;
230     tnetifs[3].type = NETIF_BRIDGE;
231     tnetifs[3].subif = NULL,
232     strlcpy(tnetifs[3].name, "bridge0", IFNAMSIZ);
233 
234     tnetifs[4].index = 5;
235     tnetifs[4].argv = 1;
236     tnetifs[4].child = 0;
237     tnetifs[4].type = NETIF_BONDING;
238     tnetifs[4].subif = NULL,
239     strlcpy(tnetifs[4].name, "lagg0", IFNAMSIZ);
240     strlcpy(tnetifs[4].description, "lagg0", IFDESCRSIZE);
241 
242     tnetifs[5].index = 3;
243     tnetifs[5].argv = 1;
244     tnetifs[5].child = 0;
245     tnetifs[5].type = NETIF_REGULAR;
246     tnetifs[5].subif = NULL,
247     strlcpy(tnetifs[5].name, "eth1", IFNAMSIZ);
248     strlcpy(tnetifs[5].description, "eth1", IFDESCRSIZE);
249 
250     TAILQ_INSERT_TAIL(netifs, &tnetifs[0], entries);
251     TAILQ_INSERT_TAIL(netifs, &tnetifs[1], entries);
252     TAILQ_INSERT_TAIL(netifs, &tnetifs[2], entries);
253     TAILQ_INSERT_TAIL(netifs, &tnetifs[3], entries);
254     TAILQ_INSERT_TAIL(netifs, &tnetifs[4], entries);
255     TAILQ_INSERT_TAIL(netifs, &tnetifs[5], entries);
256 
257     // netif_iter checks
258     mark_point();
259     netif = NULL;
260     fail_unless (netif_iter(netif, NULL) == NULL,
261 	"NULL should be returned on invalid netifs");
262 
263     netif = NULL;
264     netif = netif_iter(netif, netifs);
265     fail_unless (netif == &tnetifs[0], "the first netif should be returned");
266     netif = netif_iter(netif, netifs);
267     fail_unless (netif == &tnetifs[5], "the sixth netif should be returned");
268     netif = netif_iter(netif, netifs);
269     fail_unless (netif == NULL, "NULL should be returned");
270 
271     netif = NULL;
272     options |= OPT_ARGV;
273     netif = netif_iter(netif, netifs);
274     fail_unless (netif == &tnetifs[1], "the second netif should be returned");
275     netif = netif_iter(netif, netifs);
276     fail_unless (netif == &tnetifs[5], "the sixth netif should be returned");
277     netif = netif_iter(netif, netifs);
278     fail_unless (netif == NULL, "NULL should be returned");
279 
280 
281     // subif_iter checks
282     mark_point();
283     netif = &tnetifs[0];
284     subif = NULL;
285     subif = subif_iter(subif, subif);
286     fail_unless (subif == NULL, "NULL should be returned");
287     subif = subif_iter(subif, netif);
288     fail_unless (subif == &tnetifs[1], "the second netif should be returned");
289     subif = subif_iter(subif, netif);
290     fail_unless (subif == &tnetifs[2], "the third netif should be returned");
291     subif = subif_iter(subif, netif);
292     fail_unless (subif == NULL, "NULL should be returned");
293 
294     netif = &tnetifs[3];
295     subif = NULL;
296     subif = subif_iter(subif, netif);
297     fail_unless (subif == NULL, "NULL should be returned");
298 
299     netif = &tnetifs[4];
300     subif = NULL;
301     subif = subif_iter(subif, netif);
302     fail_unless (subif == NULL, "NULL should be returned");
303 
304     netif = &tnetifs[5];
305     subif = NULL;
306     subif = subif_iter(subif, netif);
307     fail_unless (subif == &tnetifs[5], "the sixth netif should be returned");
308     subif = subif_iter(subif, netif);
309     fail_unless (subif == NULL, "NULL should be returned");
310 
311 
312     // netif_byindex checks
313     mark_point();
314     fail_unless (netif_byindex(netifs, 0) == &tnetifs[0],
315 	"incorrect netif struct returned");
316     fail_unless (netif_byindex(netifs, 1) == &tnetifs[1],
317 	"incorrect netif struct returned");
318     fail_unless (netif_byindex(netifs, 2) == &tnetifs[2],
319 	"incorrect netif struct returned");
320     fail_unless (netif_byindex(netifs, 3) == &tnetifs[5],
321 	"incorrect netif struct returned");
322     fail_unless (netif_byindex(netifs, 6) == NULL,
323 	"NULL should be returned on not found netif");
324 
325 
326     // netif_byname checks
327     mark_point();
328     fail_unless (netif_byname(netifs, "bond0") == &tnetifs[0],
329 	"incorrect netif struct returned");
330     fail_unless (netif_byname(netifs, "eth0") == &tnetifs[1],
331 	"incorrect netif struct returned");
332     fail_unless (netif_byname(netifs, "eth2") == &tnetifs[2],
333 	"incorrect netif struct returned");
334     fail_unless (netif_byname(netifs, "eth1") == &tnetifs[5],
335 	"incorrect netif struct returned");
336     fail_unless (netif_byname(netifs, "eth3") == NULL,
337 	"NULL should be returned on not found netif");
338 
339     // XXX: netif_byaddr checks
340 
341     msg = my_malloc(PARENT_MSG_SIZ);
342     netif = netif_byname(netifs, "eth0");
343     msg->index = netif->index;
344     msg->proto = PROTO_LLDP;
345     memcpy(msg->msg + ETHER_ADDR_LEN, "\x02\x00\x01", 3);
346     msg->peer[PEER_HOSTNAME] = my_strdup("foo");
347     msg->peer[PEER_PORTNAME] = my_strdup("FastEthernet6/20");
348     TAILQ_INSERT_TAIL(&mqueue, msg, entries);
349 
350     msg = my_malloc(PARENT_MSG_SIZ);
351     netif = netif_byname(netifs, "eth2");
352     msg->index = netif->index;
353     msg->proto = PROTO_CDP;
354     memcpy(msg->msg + ETHER_ADDR_LEN, "\x02\x00\x02", 3);
355     msg->peer[PEER_HOSTNAME] = my_strdup("bar");
356     TAILQ_INSERT_TAIL(&mqueue, msg, entries);
357 
358     msg = my_malloc(PARENT_MSG_SIZ);
359     netif = netif_byname(netifs, "eth1");
360     msg->index = netif->index;
361     msg->proto = PROTO_LLDP;
362     memcpy(msg->msg + ETHER_ADDR_LEN, "\x02\x00\x03", 3);
363     msg->peer[PEER_HOSTNAME] = my_strdup("baz");
364     msg->peer[PEER_PORTNAME] = my_strdup("Ethernet4");
365     TAILQ_INSERT_TAIL(&mqueue, msg, entries);
366 
367     msg = my_malloc(PARENT_MSG_SIZ);
368     netif = netif_byname(netifs, "eth1");
369     msg->index = netif->index;
370     msg->proto = PROTO_LLDP;
371     memcpy(msg->msg + ETHER_ADDR_LEN, "\x02\x00\x04", 3);
372     msg->peer[PEER_HOSTNAME] = my_strdup("quux");
373     msg->peer[PEER_PORTNAME] = my_strdup("Ethernet5");
374     TAILQ_INSERT_TAIL(&mqueue, msg, entries);
375 
376     msg = my_malloc(PARENT_MSG_SIZ);
377     netif = netif_byname(netifs, "eth1");
378     msg->index = netif->index;
379     msg->proto = PROTO_FDP;
380     memcpy(msg->msg + ETHER_ADDR_LEN, "\x02\x00\x04", 3);
381     msg->peer[PEER_HOSTNAME] = my_strdup("quux");
382     msg->peer[PEER_PORTNAME] = my_strdup("Ethernet5");
383     TAILQ_INSERT_TAIL(&mqueue, msg, entries);
384 
385     msg = my_malloc(PARENT_MSG_SIZ);
386     netif = netif_byname(netifs, "lagg0");
387     msg->index = netif->index;
388     msg->proto = PROTO_LLDP;
389     memcpy(msg->msg + ETHER_ADDR_LEN, "\x02\x00\x05", 3);
390     TAILQ_INSERT_TAIL(&mqueue, msg, entries);
391 
392     // netif_protos checks
393     mark_point();
394     netif = netif_byname(netifs, "bond0");
395     netif_protos(netif, &mqueue);
396     fail_unless (netif->protos == ((1 << PROTO_LLDP)|(1 << PROTO_CDP)),
397 	"incorrect protos calculation");
398 
399     netif = netif_byname(netifs, "eth1");
400     netif_protos(netif, &mqueue);
401     fail_unless (netif->protos == ((1 << PROTO_LLDP)|(1 << PROTO_FDP)),
402 	"incorrect protos calculation");
403 
404     netif = netif_byname(netifs, "lagg0");
405     netif_protos(netif, &mqueue);
406     fail_unless (netif->protos == 0, "incorrect protos calculation");
407 
408     // netif_descr checks
409     mark_point();
410     msock = spair[1];
411     mreq = my_malloc(PARENT_REQ_MAX);
412     mreq->len = IFDESCRSIZE;
413 
414     netif = netif_byname(netifs, "bond0");
415     descr = "";
416     WRAP_WRITE(spair[0], mreq, PARENT_REQ_LEN(mreq->len));
417     netif_descr(netif, &mqueue);
418     WRAP_REQ_READ(spair[0], mreq, len);
419     fail_unless (mreq->op == PARENT_DESCR,
420 	"incorrect command: %d", mreq->op);
421     fail_unless (mreq->index == netif->index,
422 	"incorrect interface index: %d", mreq->index);
423     fail_unless (mreq->len == strlen(descr) + 1,
424 	"incorrect message length: %d", mreq->len);
425     fail_unless (strncmp(mreq->buf, descr, IFDESCRSIZE) == 0,
426 	"incorrect interface description: %s", mreq->buf);
427 
428     netif = netif_byname(netifs, "eth0");
429     descr = "connected to foo (Fa6/20)";
430     WRAP_WRITE(spair[0], mreq, PARENT_REQ_LEN(mreq->len));
431     netif_descr(netif, &mqueue);
432     WRAP_REQ_READ(spair[0], mreq, len);
433     fail_unless (mreq->op == PARENT_DESCR,
434 	"incorrect command: %d", mreq->op);
435     fail_unless (mreq->index == netif->index,
436 	"incorrect interface index: %d", mreq->index);
437     fail_unless (mreq->len == strlen(descr) + 1,
438 	"incorrect message length: %d", mreq->len);
439     fail_unless (strncmp(mreq->buf, descr, IFDESCRSIZE) == 0,
440 	"incorrect interface description: %s", mreq->buf);
441 
442     netif = netif_byname(netifs, "eth2");
443     descr = "connected to bar";
444     WRAP_WRITE(spair[0], mreq, PARENT_REQ_LEN(mreq->len));
445     netif_descr(netif, &mqueue);
446     WRAP_REQ_READ(spair[0], mreq, len);
447     fail_unless (mreq->op == PARENT_DESCR,
448 	"incorrect command: %d", mreq->op);
449     fail_unless (mreq->index == netif->index,
450 	"incorrect interface index: %d", mreq->index);
451     fail_unless (mreq->len == strlen(descr) + 1,
452 	"incorrect message length: %d", mreq->len);
453     fail_unless (strncmp(mreq->buf, descr, IFDESCRSIZE) == 0,
454 	"incorrect interface description: %s", mreq->buf);
455 
456     netif = netif_byname(netifs, "eth1");
457     descr = "connected to 2 peers";
458     WRAP_WRITE(spair[0], mreq, PARENT_REQ_LEN(mreq->len));
459     netif_descr(netif, &mqueue);
460     WRAP_REQ_READ(spair[0], mreq, len);
461     fail_unless (mreq->op == PARENT_DESCR,
462 	"incorrect command: %d", mreq->op);
463     fail_unless (mreq->index == netif->index,
464 	"incorrect interface index: %d", mreq->index);
465     fail_unless (mreq->len == strlen(descr) + 1,
466 	"incorrect message length: %d", mreq->len);
467     fail_unless (strncmp(mreq->buf, descr, IFDESCRSIZE) == 0,
468 	"incorrect interface description: %s", mreq->buf);
469 
470     netif = netif_byname(netifs, "lagg0");
471     descr = "";
472     WRAP_WRITE(spair[0], mreq, PARENT_REQ_LEN(mreq->len));
473     netif_descr(netif, &mqueue);
474     WRAP_REQ_READ(spair[0], mreq, len);
475     fail_unless (mreq->op == PARENT_DESCR,
476 	"incorrect command: %d", mreq->op);
477     fail_unless (mreq->index == netif->index,
478 	"incorrect interface index: %d", mreq->index);
479     fail_unless (mreq->len == strlen(descr) + 1,
480 	"incorrect message length: %d", mreq->len);
481     fail_unless (strncmp(mreq->buf, descr, IFDESCRSIZE) == 0,
482 	"incorrect interface description: %s", mreq->buf);
483 
484     free(mreq);
485     TAILQ_FOREACH_SAFE(msg, &mqueue, entries, nmsg) {
486 	TAILQ_REMOVE(&mqueue, msg, entries);
487 	peer_free(msg->peer);
488 	free(msg);
489     }
490     TAILQ_FOREACH_SAFE(netif, &nqueue, entries, subif) {
491 	TAILQ_REMOVE(&nqueue, netif, entries);
492     }
493 
494     close(spair[0]);
495     close(spair[1]);
496 }
497 END_TEST
498 
START_TEST(test_read_line)499 START_TEST(test_read_line) {
500     char line[128];
501     const char *data = "0123456789ABCDEF";
502     const char *null =  _PATH_DEVNULL;
503     const char *file = "testfile";
504     char *prefix, *path = NULL;
505 
506     if ((prefix = getenv("srcdir")) == NULL)
507 	prefix = ".";
508 
509     fail_if(asprintf(&path, "%s/%s", prefix, file) == -1, "asprintf failed");
510 
511     fail_unless (read_line("non-existant", line, 0) == 0,
512 	"0 should be returned on a missing file");
513 
514     fail_unless (read_line(null, line, 10) == 0,
515 	"0 should be returned on a unreadable file");
516 
517     fail_unless (read_line(path, line, 0) == 0,
518 	"0 should be returned on zero len request");
519 
520     fail_unless (read_line(path, line, 1) == 0,
521 	"0 bytes should be returned");
522 
523     fail_unless (read_line(path, line, 2) == 1,
524 	"1 bytes should be returned");
525 
526     fail_unless (read_line(path, line, 10) == 9,
527 	"9 bytes should be returned");
528 
529     fail_unless (read_line(path, line, 17) == 16,
530 	"16 bytes should be returned");
531 
532     fail_unless (strncmp(line, data, strlen(data)) == 0,
533 	"invalid line returned");
534 
535     fail_unless (read_line(path, line, 18) == 16,
536 	"16 bytes should be returned");
537 
538     fail_unless (strncmp(line, data, strlen(data)) == 0,
539 	"invalid line returned");
540 
541     free(path);
542 }
543 END_TEST
544 
START_TEST(test_my_cksum)545 START_TEST(test_my_cksum) {
546     const char *data = "0123456789ABCDEF";
547     uint16_t sum;
548     uint8_t cisco;
549 
550     cisco = 0;
551     sum = ntohs(my_chksum(data, strlen(data), cisco));
552     fail_unless(sum == 12585,
553 	"IP checksum result should be 12585 not %d", sum);
554 
555     cisco = 1;
556     sum = ntohs(my_chksum(data, strlen(data), cisco));
557     fail_unless(sum == 12585,
558 	"(Cisco) IP checksum result should be 12585 not %d", sum);
559 
560     cisco = 0;
561     sum = ntohs(my_chksum(data, strlen(data) - 1, cisco));
562     fail_unless(sum == 12655,
563 	"IP checksum result should be 12655 not %d", sum);
564 
565     cisco = 1;
566     sum = ntohs(my_chksum(data, strlen(data) - 1, cisco));
567     fail_unless(sum ==  30250,
568 	"(Cisco) IP checksum result should be 30250 not %d", sum);
569 }
570 END_TEST
571 
START_TEST(test_my_priv)572 START_TEST(test_my_priv) {
573     struct passwd *pwd = NULL;
574     struct stat sb;
575     const char *errstr = NULL;
576     char path[MAXPATHLEN + 1] = {};
577 
578     loglevel = INFO;
579     errno = EPERM;
580 
581     if ((pwd = getpwnam("root")) == NULL)
582 	return;
583     if (stat(_PATH_DEVNULL, &sb) != 0)
584 	return;
585 
586     mark_point();
587     errstr = "unable to setgroups";
588     check_wrap_fail |= FAIL_SETGRP;
589     WRAP_FATAL_START();
590     my_drop_privs(pwd);
591     WRAP_FATAL_END();
592     check_wrap_fail &= ~FAIL_SETGRP;
593     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
594 	"incorrect message logged: %s", check_wrap_errstr);
595 
596     mark_point();
597 #ifdef HAVE_SETRESGID
598     errstr = "unable to setresgid";
599 #elif defined(HAVE_SETREGID)
600     errstr = "unable to setregid";
601 #endif
602     check_wrap_fail |= FAIL_SETRESGID;
603     check_wrap_fake |= FAKE_SETGRP;
604     WRAP_FATAL_START();
605     my_drop_privs(pwd);
606     WRAP_FATAL_END();
607     check_wrap_fail &= ~FAIL_SETRESGID;
608     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
609 	"incorrect message logged: %s", check_wrap_errstr);
610 
611     mark_point();
612 #ifdef HAVE_SETRESUID
613     errstr = "unable to setresuid";
614 #elif defined(HAVE_SETREUID)
615     errstr = "unable to setreuid";
616 #endif
617     check_wrap_fail |= FAIL_SETRESUID;
618     check_wrap_fake |= FAKE_SETRESGID;
619     WRAP_FATAL_START();
620     my_drop_privs(pwd);
621     WRAP_FATAL_END();
622     check_wrap_fail &= ~FAIL_SETRESUID;
623     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
624 	"incorrect message logged: %s", check_wrap_errstr);
625 
626     mark_point();
627     errno = 0;
628     errstr = "check";
629     my_log(CRIT, errstr);
630     check_wrap_fake |= FAKE_SETRESUID;
631     WRAP_FATAL_START();
632     my_drop_privs(pwd);
633     WRAP_FATAL_END();
634     check_wrap_fail = 0;
635     check_wrap_fake = 0;
636     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
637 	"incorrect message logged: %s", check_wrap_errstr);
638 
639     mark_point();
640     errstr = "chroot path does not begin at root";
641     memset(path, 'a', MAXPATHLEN);
642     WRAP_FATAL_START();
643     my_chroot(path);
644     WRAP_FATAL_END();
645     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
646 	"incorrect message logged: %s", check_wrap_errstr);
647 
648     mark_point();
649     errstr = "chroot path too long";
650     path[0] = '/';
651     WRAP_FATAL_START();
652     my_chroot(path);
653     WRAP_FATAL_END();
654     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
655 	"incorrect message logged: %s", check_wrap_errstr);
656 
657     mark_point();
658     errstr = "stat(\"/inexistant\"): ";
659     WRAP_FATAL_START();
660     my_chroot("/inexistant");
661     WRAP_FATAL_END();
662     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
663 	"incorrect message logged: %s", check_wrap_errstr);
664 
665     mark_point();
666     errstr = "bad ownership or modes for chroot";
667     WRAP_FATAL_START();
668     my_chroot(_PATH_DEVNULL);
669     WRAP_FATAL_END();
670     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
671 	"incorrect message logged: %s", check_wrap_errstr);
672 
673     mark_point();
674     if (stat(_PATH_DEV, &sb) != 0)
675 	return;
676     if (sb.st_uid != 0 || (sb.st_mode & 022) != 0)
677 	return;
678     if (stat(_PATH_CONSOLE, &sb) != 0)
679 	return;
680     if (sb.st_uid != 0 || (sb.st_mode & 022) != 0)
681 	return;
682 
683     mark_point();
684     errstr = "chroot path \"" _PATH_CONSOLE "\" is not a directory";
685     WRAP_FATAL_START();
686     my_chroot(_PATH_CONSOLE);
687     WRAP_FATAL_END();
688     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
689 	"incorrect message logged: %s", check_wrap_errstr);
690 
691     mark_point();
692     errstr = "unable to chdir to chroot path";
693     strlcpy(path, "/", MAXPATHLEN);
694     check_wrap_fail |= FAIL_CHDIR;
695     WRAP_FATAL_START();
696     my_chroot(path);
697     WRAP_FATAL_END();
698     check_wrap_fail &= ~FAIL_CHDIR;
699     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
700 	"incorrect message logged: %s", check_wrap_errstr);
701 
702     mark_point();
703     errstr = "chroot(\"/\"):";
704     check_wrap_fail |= FAIL_CHROOT;
705     check_wrap_fake |= FAKE_CHDIR;
706     WRAP_FATAL_START();
707     my_chroot(path);
708     WRAP_FATAL_END();
709     check_wrap_fail &= ~FAIL_CHROOT;
710     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
711 	"incorrect message logged: %s", check_wrap_errstr);
712 
713     mark_point();
714     errno = 0;
715     errstr = "check";
716     my_log(CRIT, errstr);
717     check_wrap_fake |= FAKE_CHROOT;
718     WRAP_FATAL_START();
719     my_chroot(path);
720     WRAP_FATAL_END();
721     check_wrap_fail = 0;
722     check_wrap_fake = 0;
723     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
724 	"incorrect message logged: %s", check_wrap_errstr);
725 }
726 END_TEST
727 
START_TEST(test_portname_abbr)728 START_TEST(test_portname_abbr) {
729     char *portname = NULL;
730 
731     portname = my_strdup("FastEthernet42/42");
732     portname_abbr(portname);
733     fail_unless(strcmp(portname, "Fa42/42") == 0,
734 	"unexpected portname: %s", portname);
735     free(portname);
736 
737     portname = my_strdup("GigabitEthernet42");
738     portname_abbr(portname);
739     fail_unless(strcmp(portname, "Gi42") == 0,
740 	"unexpected portname: %s", portname);
741     free(portname);
742 
743     portname = my_strdup("TenGigabitEthernet0/86");
744     portname_abbr(portname);
745     fail_unless(strcmp(portname, "Te0/86") == 0,
746 	"unexpected portname: %s", portname);
747     free(portname);
748 
749     portname = my_strdup("Ethernet0/86");
750     portname_abbr(portname);
751     fail_unless(strcmp(portname, "Eth0/86") == 0,
752 	"unexpected portname: %s", portname);
753     free(portname);
754 
755     portname = my_strdup("eth0");
756     portname_abbr(portname);
757     fail_unless(strcmp(portname, "eth0") == 0,
758 	"unexpected portname: %s", portname);
759     free(portname);
760 }
761 END_TEST
762 
START_TEST(test_pcap)763 START_TEST(test_pcap) {
764     int spair[2];
765     ssize_t len;
766     const char *errstr = NULL;
767     char buf[1024];
768     struct pcap_file_header pcap_fhdr = {};
769     struct parent_msg msg = {};
770 
771     loglevel = INFO;
772     my_socketpair(spair);
773 
774     mark_point();
775     errstr = "stdin fd not available";
776     my_log(CRIT, "check");
777     WRAP_FATAL_START();
778     my_pcap_init(-1);
779     WRAP_FATAL_END();
780     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
781 	"incorrect message logged: %s", check_wrap_errstr);
782 
783     mark_point();
784     my_pcap_init(spair[0]);
785     len = read(spair[1], &pcap_fhdr, sizeof(pcap_fhdr));
786     fail_unless(len == sizeof(pcap_fhdr),
787 		"failed to read pcap header");
788     fail_unless(pcap_fhdr.magic == PCAP_MAGIC,
789 		"invalid pcap header returned");
790     fail_unless(pcap_fhdr.snaplen == ETHER_MAX_LEN,
791 		"invalid pcap header returned");
792     fail_unless(pcap_fhdr.linktype == DLT_EN10MB,
793 		"invalid pcap header returned");
794 
795     mark_point();
796     errstr = "check";
797     my_log(CRIT, errstr);
798     msg.len = 1;
799     my_pcap_write(&msg);
800     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
801 	"incorrect message logged: %s", check_wrap_errstr);
802     len = read(spair[1], buf, 1024);
803     fail_unless(len == (PCAP_PKTHDR_SIZ + msg.len),
804 		"failed to read pcap record");
805 
806     mark_point();
807     msg.len = ETHER_MIN_LEN;
808     my_pcap_write(&msg);
809     fail_unless (strncmp(check_wrap_errstr, errstr, strlen(errstr)) == 0,
810 	"incorrect message logged: %s", check_wrap_errstr);
811     len = read(spair[1], buf, 1024);
812     fail_unless(len == (PCAP_PKTHDR_SIZ + msg.len),
813 		"failed to read pcap record");
814 
815     close(spair[0]);
816     close(spair[1]);
817 }
818 END_TEST
819 
util_suite(void)820 Suite * util_suite (void) {
821     Suite *s = suite_create("util.c");
822 
823     // util test case
824     TCase *tc_util = tcase_create("util");
825     tcase_add_test(tc_util, test_my);
826     tcase_add_test(tc_util, test_my_mreq);
827     tcase_add_test(tc_util, test_netif);
828     tcase_add_test(tc_util, test_read_line);
829     tcase_add_test(tc_util, test_my_cksum);
830     tcase_add_test(tc_util, test_my_priv);
831     tcase_add_test(tc_util, test_portname_abbr);
832     tcase_add_test(tc_util, test_pcap);
833     suite_add_tcase(s, tc_util);
834 
835     return s;
836 }
837 
main(void)838 int main (void) {
839     int number_failed;
840     Suite *s = util_suite ();
841     SRunner *sr = srunner_create (s);
842     srunner_run_all (sr, CK_NORMAL);
843     number_failed = srunner_ntests_failed (sr);
844     srunner_free (sr);
845     return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
846 }
847 
848