1 /*
2  * Copyright (c) 2018-2021, OARC, Inc.
3  * All rights reserved.
4  *
5  * This file is part of dnsjit.
6  *
7  * dnsjit is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * dnsjit is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with dnsjit.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include "filter/layer.h"
24 #include "core/assert.h"
25 
26 #include <string.h>
27 #include <pcap/pcap.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <netinet/ip.h>
32 #include <netinet/ip6.h>
33 #ifdef HAVE_NET_ETHERNET_H
34 #include <net/ethernet.h>
35 #endif
36 #ifdef HAVE_NET_ETHERTYPES_H
37 #include <net/ethertypes.h>
38 #endif
39 #ifdef HAVE_ENDIAN_H
40 #include <endian.h>
41 #else
42 #ifdef HAVE_SYS_ENDIAN_H
43 #include <sys/endian.h>
44 #else
45 #ifdef HAVE_MACHINE_ENDIAN_H
46 #include <machine/endian.h>
47 #endif
48 #endif
49 #endif
50 #ifdef HAVE_BYTESWAP_H
51 #include <byteswap.h>
52 #endif
53 #ifndef bswap_16
54 #ifndef bswap16
55 #define bswap_16(x) swap16(x)
56 #define bswap_32(x) swap32(x)
57 #define bswap_64(x) swap64(x)
58 #else
59 #define bswap_16(x) bswap16(x)
60 #define bswap_32(x) bswap32(x)
61 #define bswap_64(x) bswap64(x)
62 #endif
63 #endif
64 
65 #define N_IEEE802 3
66 
67 static core_log_t     _log      = LOG_T_INIT("filter.layer");
68 static filter_layer_t _defaults = {
69     LOG_T_INIT_OBJ("filter.layer"),
70     0, 0,
71     0, 0,
72     0,
73     CORE_OBJECT_NULL_INIT(0),
74     CORE_OBJECT_ETHER_INIT(0),
75     CORE_OBJECT_LOOP_INIT(0),
76     CORE_OBJECT_LINUXSLL_INIT(0),
77     0, { CORE_OBJECT_IEEE802_INIT(0), CORE_OBJECT_IEEE802_INIT(0), CORE_OBJECT_IEEE802_INIT(0) },
78     CORE_OBJECT_IP_INIT(0),
79     CORE_OBJECT_IP6_INIT(0),
80     CORE_OBJECT_GRE_INIT(0),
81     CORE_OBJECT_ICMP_INIT(0),
82     CORE_OBJECT_ICMP6_INIT(0),
83     CORE_OBJECT_UDP_INIT(0),
84     CORE_OBJECT_TCP_INIT(0),
85     CORE_OBJECT_PAYLOAD_INIT(0)
86 };
87 
filter_layer_log()88 core_log_t* filter_layer_log()
89 {
90     return &_log;
91 }
92 
filter_layer_init(filter_layer_t * self)93 void filter_layer_init(filter_layer_t* self)
94 {
95     mlassert_self();
96 
97     *self = _defaults;
98 }
99 
filter_layer_destroy(filter_layer_t * self)100 void filter_layer_destroy(filter_layer_t* self)
101 {
102     mlassert_self();
103 }
104 
105 #define need4x2(v1, v2, p, l) \
106     if (l < 1) {              \
107         break;                \
108     }                         \
109     v1 = (*p) >> 4;           \
110     v2 = (*p) & 0xf;          \
111     p += 1;                   \
112     l -= 1
113 
114 #define need8(v, p, l) \
115     if (l < 1) {       \
116         break;         \
117     }                  \
118     v = *p;            \
119     p += 1;            \
120     l -= 1
121 
_need16(const void * ptr)122 static inline uint16_t _need16(const void* ptr)
123 {
124     uint16_t v;
125     memcpy(&v, ptr, sizeof(v));
126     return be16toh(v);
127 }
128 
129 #define need16(v, p, l) \
130     if (l < 2) {        \
131         break;          \
132     }                   \
133     v = _need16(p);     \
134     p += 2;             \
135     l -= 2
136 
137 #define needr16(v, p, l)      \
138     if (l < 2) {              \
139         break;                \
140     }                         \
141     v = bswap_16(_need16(p)); \
142     p += 2;                   \
143     l -= 2
144 
_need32(const void * ptr)145 static inline uint32_t _need32(const void* ptr)
146 {
147     uint32_t v;
148     memcpy(&v, ptr, sizeof(v));
149     return be32toh(v);
150 }
151 
152 #define need32(v, p, l) \
153     if (l < 4) {        \
154         break;          \
155     }                   \
156     v = _need32(p);     \
157     p += 4;             \
158     l -= 4
159 
160 #define needr32(v, p, l)      \
161     if (l < 4) {              \
162         break;                \
163     }                         \
164     v = bswap_32(_need32(p)); \
165     p += 4;                   \
166     l -= 4
167 
168 #define needxb(b, x, p, l) \
169     if (l < x) {           \
170         break;             \
171     }                      \
172     memcpy(b, p, x);       \
173     p += x;                \
174     l -= x
175 
176 #define advancexb(x, p, l) \
177     if (l < x) {           \
178         break;             \
179     }                      \
180     p += x;                \
181     l -= x
182 
183 //static int _ip(filter_layer_t* self, const core_object_t* obj, const unsigned char* pkt, size_t len);
184 
_proto(filter_layer_t * self,uint8_t proto,const core_object_t * obj,const unsigned char * pkt,size_t len)185 static inline int _proto(filter_layer_t* self, uint8_t proto, const core_object_t* obj, const unsigned char* pkt, size_t len)
186 {
187     switch (proto) {
188     case IPPROTO_GRE: {
189         core_object_gre_t* gre = &self->gre;
190         gre->obj_prev          = obj;
191 
192         need16(gre->gre_flags, pkt, len);
193         need16(gre->ether_type, pkt, len);
194 
195         /* TODO: Incomplete, check RFC 1701 */
196 
197         self->produced = (core_object_t*)gre;
198 
199         // if (gre.gre_flags & 0x1) {
200         //     need16(gre.checksum, pkt, len);
201         // }
202         // if (gre.gre_flags & 0x4) {
203         //     need16(gre.key, pkt, len);
204         // }
205         // if (gre.gre_flags & 0x8) {
206         //     need16(gre.sequence, pkt, len);
207         // }
208         //
209         // switch (gre.ether_type) {
210         // case ETHERTYPE_IP:
211         // case ETHERTYPE_IPV6:
212         //     return _ip(self, (core_object_t*)gre, pkt, len);
213         //
214         // default:
215         //     break;
216         // }
217         break;
218     }
219     case IPPROTO_ICMP: {
220         core_object_icmp_t* icmp = &self->icmp;
221         icmp->obj_prev           = obj;
222 
223         need8(icmp->type, pkt, len);
224         need8(icmp->code, pkt, len);
225         need16(icmp->cksum, pkt, len);
226 
227         self->produced = (core_object_t*)icmp;
228         break;
229     }
230     case IPPROTO_ICMPV6: {
231         core_object_icmp6_t* icmp6 = &self->icmp6;
232         icmp6->obj_prev            = obj;
233 
234         need8(icmp6->type, pkt, len);
235         need8(icmp6->code, pkt, len);
236         need16(icmp6->cksum, pkt, len);
237 
238         self->produced = (core_object_t*)icmp6;
239         break;
240     }
241     case IPPROTO_UDP: {
242         core_object_udp_t*     udp     = &self->udp;
243         core_object_payload_t* payload = &self->payload;
244         udp->obj_prev                  = obj;
245 
246         need16(udp->sport, pkt, len);
247         need16(udp->dport, pkt, len);
248         need16(udp->ulen, pkt, len);
249         need16(udp->sum, pkt, len);
250 
251         payload->obj_prev = (core_object_t*)udp;
252 
253         /* Check for padding */
254         if (len > udp->ulen) {
255             payload->padding = len - udp->ulen;
256             payload->len     = len - payload->padding;
257         } else {
258             payload->padding = 0;
259             payload->len     = len;
260         }
261         payload->payload = (uint8_t*)pkt;
262 
263         self->produced = (core_object_t*)payload;
264         break;
265     }
266     case IPPROTO_TCP: {
267         core_object_tcp_t*     tcp     = &self->tcp;
268         core_object_payload_t* payload = &self->payload;
269         tcp->obj_prev                  = obj;
270 
271         need16(tcp->sport, pkt, len);
272         need16(tcp->dport, pkt, len);
273         need32(tcp->seq, pkt, len);
274         need32(tcp->ack, pkt, len);
275         need4x2(tcp->off, tcp->x2, pkt, len);
276         need8(tcp->flags, pkt, len);
277         need16(tcp->win, pkt, len);
278         need16(tcp->sum, pkt, len);
279         need16(tcp->urp, pkt, len);
280         if (tcp->off > 5) {
281             tcp->opts_len = (tcp->off - 5) * 4;
282             needxb(tcp->opts, tcp->opts_len, pkt, len);
283         } else {
284             tcp->opts_len = 0;
285         }
286 
287         payload->obj_prev = (core_object_t*)tcp;
288 
289         /* Check for padding */
290         if (obj->obj_type == CORE_OBJECT_IP && len > (((const core_object_ip_t*)obj)->len - (((const core_object_ip_t*)obj)->hl * 4))) {
291             payload->padding = len - (((const core_object_ip_t*)obj)->len - (((const core_object_ip_t*)obj)->hl * 4));
292             payload->len     = len - payload->padding;
293         } else if (obj->obj_type == CORE_OBJECT_IP6 && len > ((const core_object_ip6_t*)obj)->plen) {
294             payload->padding = len - ((const core_object_ip6_t*)obj)->plen;
295             payload->len     = len - payload->padding;
296         } else {
297             payload->padding = 0;
298             payload->len     = len;
299         }
300 
301         payload->payload = (uint8_t*)pkt;
302 
303         self->produced = (core_object_t*)payload;
304         break;
305     }
306     default:
307         self->produced = obj;
308         break;
309     }
310 
311     return 0;
312 }
313 
_ip(filter_layer_t * self,const core_object_t * obj,const unsigned char * pkt,size_t len)314 static inline int _ip(filter_layer_t* self, const core_object_t* obj, const unsigned char* pkt, size_t len)
315 {
316     if (len) {
317         switch ((*pkt >> 4)) {
318         case 4: {
319             core_object_ip_t* ip = &self->ip;
320 
321             ip->obj_prev = obj;
322 
323             need4x2(ip->v, ip->hl, pkt, len);
324             need8(ip->tos, pkt, len);
325             need16(ip->len, pkt, len);
326             need16(ip->id, pkt, len);
327             need16(ip->off, pkt, len);
328             need8(ip->ttl, pkt, len);
329             need8(ip->p, pkt, len);
330             need16(ip->sum, pkt, len);
331             needxb(&ip->src, 4, pkt, len);
332             needxb(&ip->dst, 4, pkt, len);
333 
334             /* TODO: IPv4 options */
335 
336             if (ip->hl < 5)
337                 break;
338             if (ip->hl > 5) {
339                 advancexb((ip->hl - 5) * 4, pkt, len);
340             }
341 
342             /* Check reported length for missing payload */
343             if (ip->len < (ip->hl * 4)) {
344                 break;
345             }
346             if (len < (ip->len - (ip->hl * 4))) {
347                 break;
348             }
349 
350             if (ip->off & 0x2000 || ip->off & 0x1fff) {
351                 core_object_payload_t* payload = &self->payload;
352 
353                 payload->obj_prev = (core_object_t*)ip;
354 
355                 /* Check for padding */
356                 if (len > (ip->len - (ip->hl * 4))) {
357                     payload->padding = len - (ip->len - (ip->hl * 4));
358                     payload->len     = len - payload->padding;
359                 } else {
360                     payload->padding = 0;
361                     payload->len     = len;
362                 }
363                 payload->payload = (uint8_t*)pkt;
364 
365                 self->produced = (core_object_t*)payload;
366                 return 0;
367             }
368 
369             return _proto(self, ip->p, (core_object_t*)ip, pkt, len);
370         }
371         case 6: {
372             core_object_ip6_t* ip6 = &self->ip6;
373             struct ip6_ext     ext;
374 
375             ip6->obj_prev = obj;
376             ip6->is_frag = ip6->have_rtdst = 0;
377 
378             need32(ip6->flow, pkt, len);
379             need16(ip6->plen, pkt, len);
380             need8(ip6->nxt, pkt, len);
381             need8(ip6->hlim, pkt, len);
382             needxb(&ip6->src, 16, pkt, len);
383             needxb(&ip6->dst, 16, pkt, len);
384 
385             /* Check reported length for missing payload */
386             if (len < ip6->plen) {
387                 break;
388             }
389 
390             ext.ip6e_nxt = ip6->nxt;
391             ext.ip6e_len = 0;
392             while (ext.ip6e_nxt != IPPROTO_NONE
393                    && ext.ip6e_nxt != IPPROTO_GRE
394                    && ext.ip6e_nxt != IPPROTO_ICMPV6
395                    && ext.ip6e_nxt != IPPROTO_UDP
396                    && ext.ip6e_nxt != IPPROTO_TCP) {
397 
398                 /*
399                  * Advance to the start of next header, this may not be needed
400                  * if it's the first header or if the header is supported.
401                  */
402                 if (ext.ip6e_len) {
403                     advancexb(ext.ip6e_len * 8, pkt, len);
404                 }
405 
406                 /* TODO: Store IPv6 headers? */
407 
408                 /* Handle supported headers */
409                 if (ext.ip6e_nxt == IPPROTO_FRAGMENT) {
410                     if (ip6->is_frag) {
411                         return 1;
412                     }
413                     need8(ext.ip6e_nxt, pkt, len);
414                     need8(ext.ip6e_len, pkt, len);
415                     if (ext.ip6e_len) {
416                         return 1;
417                     }
418                     need16(ip6->frag_offlg, pkt, len);
419                     need32(ip6->frag_ident, pkt, len);
420                     ip6->is_frag = 1;
421                 } else if (ext.ip6e_nxt == IPPROTO_ROUTING) {
422                     struct ip6_rthdr rthdr;
423 
424                     if (ip6->have_rtdst) {
425                         return 1;
426                     }
427 
428                     need8(ext.ip6e_nxt, pkt, len);
429                     need8(ext.ip6e_len, pkt, len);
430                     need8(rthdr.ip6r_type, pkt, len);
431                     need8(rthdr.ip6r_segleft, pkt, len);
432                     advancexb(4, pkt, len);
433 
434                     if (!rthdr.ip6r_type && rthdr.ip6r_segleft) {
435                         if (ext.ip6e_len & 1) {
436                             return 1;
437                         }
438                         if (ext.ip6e_len > 2) {
439                             advancexb(ext.ip6e_len - 2, pkt, len);
440                         }
441                         needxb(ip6->rtdst, 16, pkt, len);
442                         ip6->have_rtdst = 1;
443                     }
444                 } else {
445                     need8(ext.ip6e_nxt, pkt, len);
446                     need8(ext.ip6e_len, pkt, len);
447                     advancexb(6, pkt, len);
448                 }
449             }
450 
451             if (ext.ip6e_nxt == IPPROTO_NONE || ip6->is_frag) {
452                 core_object_payload_t* payload = &self->payload;
453 
454                 payload->obj_prev = (core_object_t*)ip6;
455 
456                 /* Check for padding */
457                 if (len > ip6->plen) {
458                     payload->padding = len - ip6->plen;
459                     payload->len     = len - payload->padding;
460                 } else {
461                     payload->padding = 0;
462                     payload->len     = len;
463                 }
464                 payload->payload = (uint8_t*)pkt;
465 
466                 self->produced = (core_object_t*)payload;
467                 return 0;
468             }
469 
470             return _proto(self, ext.ip6e_nxt, (core_object_t*)ip6, pkt, len);
471         }
472         default:
473             break;
474         }
475     }
476 
477     self->produced = obj;
478 
479     return 0;
480 }
481 
_ieee802(filter_layer_t * self,uint16_t tpid,const core_object_t * obj,const unsigned char * pkt,size_t len)482 static inline int _ieee802(filter_layer_t* self, uint16_t tpid, const core_object_t* obj, const unsigned char* pkt, size_t len)
483 {
484     core_object_ieee802_t* ieee802 = &self->ieee802[self->n_ieee802];
485     uint16_t               tci;
486 
487     ieee802->obj_prev = obj;
488 
489     for (;;) {
490         ieee802->tpid = tpid;
491         need16(tci, pkt, len);
492         ieee802->pcp = (tci & 0xe000) >> 13;
493         ieee802->dei = (tci & 0x1000) >> 12;
494         ieee802->vid = tci & 0x0fff;
495         need16(ieee802->ether_type, pkt, len);
496 
497         switch (ieee802->ether_type) {
498         case 0x88a8: /* 802.1ad */
499         case 0x9100: /* 802.1 QinQ non-standard */
500             self->n_ieee802++;
501             if (self->n_ieee802 < N_IEEE802) {
502                 obj               = (const core_object_t*)ieee802;
503                 ieee802           = &self->ieee802[self->n_ieee802];
504                 ieee802->obj_prev = obj;
505                 tpid              = ieee802->ether_type;
506                 continue;
507             }
508             return 1;
509 
510         case ETHERTYPE_IP:
511         case ETHERTYPE_IPV6:
512             return _ip(self, (core_object_t*)ieee802, pkt, len);
513 
514         default:
515             break;
516         }
517         break;
518     }
519 
520     self->produced = obj;
521 
522     return 0;
523 }
524 
_link(filter_layer_t * self,const core_object_pcap_t * pcap)525 static inline int _link(filter_layer_t* self, const core_object_pcap_t* pcap)
526 {
527     const unsigned char* pkt;
528     size_t               len;
529 
530     self->n_ieee802 = 0;
531 
532     pkt = pcap->bytes;
533     len = pcap->caplen;
534 
535     switch (pcap->linktype) {
536     case DLT_NULL: {
537         core_object_null_t* null = &self->null;
538         null->obj_prev           = (core_object_t*)pcap;
539 
540         if (pcap->is_swapped) {
541             needr32(null->family, pkt, len);
542         } else {
543             need32(null->family, pkt, len);
544         }
545 
546         switch (null->family) {
547         case 2:
548         case 24:
549         case 28:
550         case 30:
551             return _ip(self, (core_object_t*)null, pkt, len);
552 
553         default:
554             break;
555         }
556         break;
557     }
558     case DLT_EN10MB: {
559         core_object_ether_t* ether = &self->ether;
560         ether->obj_prev            = (core_object_t*)pcap;
561 
562         needxb(ether->dhost, 6, pkt, len);
563         needxb(ether->shost, 6, pkt, len);
564         need16(ether->type, pkt, len);
565 
566         switch (ether->type) {
567         case 0x8100: /* 802.1q */
568         case 0x88a8: /* 802.1ad */
569         case 0x9100: /* 802.1 QinQ non-standard */
570             return _ieee802(self, ether->type, (core_object_t*)ether, pkt, len);
571 
572         case ETHERTYPE_IP:
573         case ETHERTYPE_IPV6:
574             return _ip(self, (core_object_t*)ether, pkt, len);
575 
576         default:
577             break;
578         }
579         break;
580     }
581     case DLT_LOOP: {
582         core_object_loop_t* loop = &self->loop;
583         loop->obj_prev           = (core_object_t*)pcap;
584 
585         need32(loop->family, pkt, len);
586 
587         switch (loop->family) {
588         case 2:
589         case 24:
590         case 28:
591         case 30:
592             return _ip(self, (core_object_t*)loop, pkt, len);
593 
594         default:
595             break;
596         }
597         break;
598     }
599     case DLT_RAW:
600 #ifdef DLT_IPV4
601     case DLT_IPV4:
602 #endif
603 #ifdef DLT_IPV6
604     case DLT_IPV6:
605 #endif
606         return _ip(self, (core_object_t*)pcap, pkt, len);
607     case DLT_LINUX_SLL: {
608         core_object_linuxsll_t* linuxsll = &self->linuxsll;
609         linuxsll->obj_prev               = (core_object_t*)pcap;
610 
611         need16(linuxsll->packet_type, pkt, len);
612         need16(linuxsll->arp_hardware, pkt, len);
613         need16(linuxsll->link_layer_address_length, pkt, len);
614         needxb(linuxsll->link_layer_address, 8, pkt, len);
615         need16(linuxsll->ether_type, pkt, len);
616 
617         switch (linuxsll->ether_type) {
618         case 0x8100: /* 802.1q */
619         case 0x88a8: /* 802.1ad */
620         case 0x9100: /* 802.1 QinQ non-standard */
621             return _ieee802(self, linuxsll->ether_type, (core_object_t*)linuxsll, pkt, len);
622 
623         case ETHERTYPE_IP:
624         case ETHERTYPE_IPV6:
625             return _ip(self, (core_object_t*)linuxsll, pkt, len);
626 
627         default:
628             break;
629         }
630         break;
631     }
632     /* TODO: These might be interesting to implement
633         case DLT_IPNET:
634         case DLT_PKTAP:
635         */
636     default:
637         break;
638     }
639 
640     self->produced = (core_object_t*)pcap;
641 
642     return 0;
643 }
644 
_receive(filter_layer_t * self,const core_object_t * obj)645 static void _receive(filter_layer_t* self, const core_object_t* obj)
646 {
647     mlassert_self();
648     lassert(obj, "obj is nil");
649 
650     if (!self->recv) {
651         lfatal("no receiver set");
652     }
653     if (obj->obj_type != CORE_OBJECT_PCAP) {
654         lfatal("obj is not CORE_OBJECT_PCAP");
655     }
656 
657     if (!_link(self, (core_object_pcap_t*)obj)) {
658         self->recv(self->ctx, self->produced);
659     }
660 }
661 
filter_layer_receiver()662 core_receiver_t filter_layer_receiver()
663 {
664     return (core_receiver_t)_receive;
665 }
666 
_produce(filter_layer_t * self)667 static const core_object_t* _produce(filter_layer_t* self)
668 {
669     const core_object_t* obj;
670     mlassert_self();
671 
672     obj = self->prod(self->prod_ctx);
673     if (!obj || obj->obj_type != CORE_OBJECT_PCAP || _link(self, (core_object_pcap_t*)obj)) {
674         return 0;
675     }
676 
677     return self->produced;
678 }
679 
filter_layer_producer(filter_layer_t * self)680 core_producer_t filter_layer_producer(filter_layer_t* self)
681 {
682     mlassert_self();
683 
684     if (!self->prod) {
685         lfatal("no producer set");
686     }
687 
688     return (core_producer_t)_produce;
689 }
690