21
21
#include < libexplain/ioctl.h>
22
22
#include < linux/filter.h>
23
23
#include < netpacket/packet.h>
24
+ #include " subscriberstatetable.h"
25
+ #include " select.h"
24
26
25
27
#include " dhcp_device.h"
26
28
49
51
#define OP_JSET (BPF_JMP | BPF_JSET | BPF_K) /* * bpf jset */
50
52
#define OP_LDXB (BPF_LDX | BPF_B | BPF_MSH) /* * bpf ldxb */
51
53
54
+ std::shared_ptr<swss::DBConnector> mStateDbPtr = std::make_shared<swss::DBConnector> (" STATE_DB" , 0 );
55
+ std::shared_ptr<swss::Table> mStateDbMuxTablePtr = std::make_shared<swss::Table> (
56
+ mStateDbPtr .get(), " HW_MUX_CABLE_TABLE"
57
+ );
58
+ swss::DBConnector configDb (" CONFIG_DB" , 0 );
59
+
52
60
/* * Berkeley Packet Filter program for "udp and (port 67 or port 68)".
53
61
* This program is obtained using the following command tcpdump:
54
- * `tcpdump -dd "udp and (port 67 or port 68)"`
62
+ * `tcpdump -dd "inbound and udp and (port 67 or port 68)"`
55
63
*/
56
64
static struct sock_filter dhcp_bpf_code[] = {
57
- {.code = OP_LDHA , .jt = 0 , .jf = 0 , .k = 0x0000000c }, // (000) ldh [12]
58
- {.code = OP_JEQ , .jt = 0 , .jf = 7 , .k = 0x000086dd }, // (001) jeq #0x86dd jt 2 jf 9
59
- {.code = OP_LDB , .jt = 0 , .jf = 0 , .k = 0x00000014 }, // (002) ldb [20]
60
- {.code = OP_JEQ , .jt = 0 , .jf = 18 , .k = 0x00000011 }, // (003) jeq #0x11 jt 4 jf 22
61
- {.code = OP_LDHA , .jt = 0 , .jf = 0 , .k = 0x00000036 }, // (004) ldh [54]
62
- {.code = OP_JEQ , .jt = 15 , .jf = 0 , .k = 0x00000043 }, // (005) jeq #0x43 jt 21 jf 6
63
- {.code = OP_JEQ , .jt = 14 , .jf = 0 , .k = 0x00000044 }, // (006) jeq #0x44 jt 21 jf 7
64
- {.code = OP_LDHA , .jt = 0 , .jf = 0 , .k = 0x00000038 }, // (007) ldh [56]
65
- {.code = OP_JEQ , .jt = 12 , .jf = 11 , .k = 0x00000043 }, // (008) jeq #0x43 jt 21 jf 20
66
- {.code = OP_JEQ , .jt = 0 , .jf = 12 , .k = 0x00000800 }, // (009) jeq #0x800 jt 10 jf 22
67
- {.code = OP_LDB , .jt = 0 , .jf = 0 , .k = 0x00000017 }, // (010) ldb [23]
68
- {.code = OP_JEQ , .jt = 0 , .jf = 10 , .k = 0x00000011 }, // (011) jeq #0x11 jt 12 jf 22
69
- {.code = OP_LDHA , .jt = 0 , .jf = 0 , .k = 0x00000014 }, // (012) ldh [20]
70
- {.code = OP_JSET , .jt = 8 , .jf = 0 , .k = 0x00001fff }, // (013) jset #0x1fff jt 22 jf 14
71
- {.code = OP_LDXB , .jt = 0 , .jf = 0 , .k = 0x0000000e }, // (014) ldxb 4*([14]&0xf)
72
- {.code = OP_LDHI , .jt = 0 , .jf = 0 , .k = 0x0000000e }, // (015) ldh [x + 14]
73
- {.code = OP_JEQ , .jt = 4 , .jf = 0 , .k = 0x00000043 }, // (016) jeq #0x43 jt 21 jf 17
74
- {.code = OP_JEQ , .jt = 3 , .jf = 0 , .k = 0x00000044 }, // (017) jeq #0x44 jt 21 jf 18
75
- {.code = OP_LDHI , .jt = 0 , .jf = 0 , .k = 0x00000010 }, // (018) ldh [x + 16]
76
- {.code = OP_JEQ , .jt = 1 , .jf = 0 , .k = 0x00000043 }, // (019) jeq #0x43 jt 21 jf 20
77
- {.code = OP_JEQ , .jt = 0 , .jf = 1 , .k = 0x00000044 }, // (020) jeq #0x44 jt 21 jf 22
78
- {.code = OP_RET , .jt = 0 , .jf = 0 , .k = 0x00040000 }, // (021) ret #262144
79
- {.code = OP_RET , .jt = 0 , .jf = 0 , .k = 0x00000000 }, // (022) ret #0
65
+ {.code = OP_LDHA, .jt = 0 , .jf = 0 , .k = 0xfffff004 }, // (000) ldh #fffff004
66
+ {.code = OP_JEQ, .jt = 22 , .jf = 0 , .k = 0x00000004 }, // (001) jeq #0x04 jt 22 jf 0
67
+ {.code = OP_LDHA, .jt = 0 , .jf = 0 , .k = 0x0000000c }, // (002) ldh [12]
68
+ {.code = OP_JEQ, .jt = 0 , .jf = 7 , .k = 0x000086dd }, // (003) jeq #0x86dd jt 2 jf 9
69
+ {.code = OP_LDB, .jt = 0 , .jf = 0 , .k = 0x00000014 }, // (004) ldb [20]
70
+ {.code = OP_JEQ, .jt = 0 , .jf = 18 , .k = 0x00000011 }, // (005) jeq #0x11 jt 4 jf 22
71
+ {.code = OP_LDHA, .jt = 0 , .jf = 0 , .k = 0x00000036 }, // (006) ldh [54]
72
+ {.code = OP_JEQ, .jt = 15 , .jf = 0 , .k = 0x00000043 }, // (007) jeq #0x43 jt 21 jf 6
73
+ {.code = OP_JEQ, .jt = 14 , .jf = 0 , .k = 0x00000044 }, // (008) jeq #0x44 jt 21 jf 7
74
+ {.code = OP_LDHA, .jt = 0 , .jf = 0 , .k = 0x00000038 }, // (009) ldh [56]
75
+ {.code = OP_JEQ, .jt = 12 , .jf = 11 , .k = 0x00000043 }, // (010) jeq #0x43 jt 21 jf 20
76
+ {.code = OP_JEQ, .jt = 0 , .jf = 12 , .k = 0x00000800 }, // (011) jeq #0x800 jt 10 jf 22
77
+ {.code = OP_LDB, .jt = 0 , .jf = 0 , .k = 0x00000017 }, // (012) ldb [23]
78
+ {.code = OP_JEQ, .jt = 0 , .jf = 10 , .k = 0x00000011 }, // (013) jeq #0x11 jt 12 jf 22
79
+ {.code = OP_LDHA, .jt = 0 , .jf = 0 , .k = 0x00000014 }, // (014) ldh [20]
80
+ {.code = OP_JSET, .jt = 8 , .jf = 0 , .k = 0x00001fff }, // (015) jset #0x1fff jt 22 jf 14
81
+ {.code = OP_LDXB, .jt = 0 , .jf = 0 , .k = 0x0000000e }, // (016) ldxb 4*([14]&0xf)
82
+ {.code = OP_LDHI, .jt = 0 , .jf = 0 , .k = 0x0000000e }, // (017) ldh [x + 14]
83
+ {.code = OP_JEQ, .jt = 4 , .jf = 0 , .k = 0x00000043 }, // (018) jeq #0x43 jt 21 jf 17
84
+ {.code = OP_JEQ, .jt = 3 , .jf = 0 , .k = 0x00000044 }, // (019) jeq #0x44 jt 21 jf 18
85
+ {.code = OP_LDHI, .jt = 0 , .jf = 0 , .k = 0x00000010 }, // (020) ldh [x + 16]
86
+ {.code = OP_JEQ, .jt = 1 , .jf = 0 , .k = 0x00000043 }, // (021) jeq #0x43 jt 21 jf 20
87
+ {.code = OP_JEQ, .jt = 0 , .jf = 1 , .k = 0x00000044 }, // (022) jeq #0x44 jt 21 jf 22
88
+ {.code = OP_RET, .jt = 0 , .jf = 0 , .k = 0x00040000 }, // (023) ret #262144
89
+ {.code = OP_RET, .jt = 0 , .jf = 0 , .k = 0x00000000 }, // (024) ret #0
80
90
};
81
91
82
92
/* * Filter program socket struct */
@@ -176,7 +186,7 @@ static void read_callback(int fd, short event, void *arg)
176
186
uint8_t *dhcphdr = context->buffer + DHCP_START_OFFSET;
177
187
int dhcp_option_offset = DHCP_START_OFFSET + DHCP_OPTIONS_HEADER_SIZE;
178
188
179
- if ((buffer_sz > UDP_START_OFFSET + sizeof (struct udphdr ) + DHCP_OPTIONS_HEADER_SIZE ) &&
189
+ if ((( unsigned ) buffer_sz > UDP_START_OFFSET + sizeof (struct udphdr ) + DHCP_OPTIONS_HEADER_SIZE) &&
180
190
(ntohs (udp->len ) > DHCP_OPTIONS_HEADER_SIZE)) {
181
191
int dhcp_sz = ntohs (udp->len ) < buffer_sz - UDP_START_OFFSET - sizeof (struct udphdr ) ?
182
192
ntohs (udp->len ) : buffer_sz - UDP_START_OFFSET - sizeof (struct udphdr );
@@ -221,6 +231,87 @@ static void read_callback(int fd, short event, void *arg)
221
231
}
222
232
}
223
233
234
+ /* *
235
+ * @code read_callback_dual_tor(fd, event, arg);
236
+ *
237
+ * @brief callback for libevent which is called every time out in order to read queued packet capture when dual tor mode is enabled
238
+ *
239
+ * @param fd socket to read from
240
+ * @param event libevent triggered event
241
+ * @param arg user provided argument for callback (interface context)
242
+ *
243
+ * @return none
244
+ */
245
+ static void read_callback_dual_tor (int fd, short event, void *arg)
246
+ {
247
+ dhcp_device_context_t *context = (dhcp_device_context_t *) arg;
248
+ ssize_t buffer_sz;
249
+ struct sockaddr_ll sll;
250
+ socklen_t slen = sizeof sll;
251
+
252
+ while ((event == EV_READ) &&
253
+ ((buffer_sz = recvfrom (fd, context->buffer , context->snaplen , MSG_DONTWAIT, (struct sockaddr *)&sll, &slen)) > 0 ))
254
+ {
255
+ std::string member_table = std::string (" VLAN_MEMBER|" ) + context->intf + " |" ;
256
+ char interfaceName[IF_NAMESIZE];
257
+ char *interface = if_indextoname (sll.sll_ifindex , interfaceName);
258
+ std::string state;
259
+ std::string intf (interface);
260
+ mStateDbMuxTablePtr ->hget (intf, " state" , state);
261
+ if (state != " standby" && configDb.exists (member_table.append (interface))) {
262
+ struct ether_header *ethhdr = (struct ether_header *) context->buffer ;
263
+ struct ip *iphdr = (struct ip *) (context->buffer + IP_START_OFFSET);
264
+ struct udphdr *udp = (struct udphdr *) (context->buffer + UDP_START_OFFSET);
265
+ uint8_t *dhcphdr = context->buffer + DHCP_START_OFFSET;
266
+ int dhcp_option_offset = DHCP_START_OFFSET + DHCP_OPTIONS_HEADER_SIZE;
267
+
268
+ if (((unsigned )buffer_sz > UDP_START_OFFSET + sizeof (struct udphdr ) + DHCP_OPTIONS_HEADER_SIZE) &&
269
+ (ntohs (udp->len ) > DHCP_OPTIONS_HEADER_SIZE))
270
+ {
271
+ int dhcp_sz = ntohs (udp->len ) < buffer_sz - UDP_START_OFFSET - sizeof (struct udphdr ) ?
272
+ ntohs (udp->len ) : buffer_sz - UDP_START_OFFSET - sizeof (struct udphdr );
273
+ int dhcp_option_sz = dhcp_sz - DHCP_OPTIONS_HEADER_SIZE;
274
+ const u_char *dhcp_option = context->buffer + dhcp_option_offset;
275
+ dhcp_packet_direction_t dir = (ethhdr->ether_shost [0 ] == context->mac [0 ] &&
276
+ ethhdr->ether_shost [1 ] == context->mac [1 ] &&
277
+ ethhdr->ether_shost [2 ] == context->mac [2 ] &&
278
+ ethhdr->ether_shost [3 ] == context->mac [3 ] &&
279
+ ethhdr->ether_shost [4 ] == context->mac [4 ] &&
280
+ ethhdr->ether_shost [5 ] == context->mac [5 ]) ?
281
+ DHCP_TX : DHCP_RX;
282
+ int offset = 0 ;
283
+ int stop_dhcp_processing = 0 ;
284
+ while ((offset < (dhcp_option_sz + 1 )) && dhcp_option[offset] != 255 ) {
285
+ switch (dhcp_option[offset])
286
+ {
287
+ case 53 :
288
+ if (offset < (dhcp_option_sz + 2 )) {
289
+ handle_dhcp_option_53 (context, &dhcp_option[offset], dir, iphdr, dhcphdr);
290
+ }
291
+ stop_dhcp_processing = 1 ; // break while loop since we are only interested in Option 53
292
+ break ;
293
+ default :
294
+ break ;
295
+ }
296
+
297
+ if (stop_dhcp_processing == 1 ) {
298
+ break ;
299
+ }
300
+
301
+ if (dhcp_option[offset] == 0 ) { // DHCP Option Padding
302
+ offset++;
303
+ } else {
304
+ offset += dhcp_option[offset + 1 ] + 2 ;
305
+ }
306
+ }
307
+ } else {
308
+ syslog (LOG_WARNING, " read_callback(%s): read length (%ld) is too small to capture DHCP options" ,
309
+ context->intf , buffer_sz);
310
+ }
311
+ }
312
+ }
313
+ }
314
+
224
315
/* *
225
316
* @code dhcp_device_is_dhcp_inactive(counters);
226
317
*
@@ -412,7 +503,7 @@ static int init_socket(dhcp_device_context_t *context, const char *intf)
412
503
413
504
struct sockaddr_ll addr;
414
505
memset (&addr, 0 , sizeof (addr));
415
- addr .sll_ifindex = if_nametoindex ( intf );
506
+ addr.sll_ifindex = 0 ; // any interface
416
507
addr.sll_family = AF_PACKET;
417
508
addr.sll_protocol = htons (ETH_P_ALL);
418
509
if (bind (context->sock , (struct sockaddr *) &addr, sizeof (addr))) {
@@ -553,6 +644,7 @@ int dhcp_device_start_capture(dhcp_device_context_t *context,
553
644
in_addr_t giaddr_ip)
554
645
{
555
646
int rv = -1 ;
647
+ struct event *ev;
556
648
557
649
do {
558
650
if (context == NULL ) {
@@ -579,7 +671,11 @@ int dhcp_device_start_capture(dhcp_device_context_t *context,
579
671
break ;
580
672
}
581
673
582
- struct event * ev = event_new (base , context -> sock , EV_READ | EV_PERSIST , read_callback , context );
674
+ if (dual_tor_sock)
675
+ ev = event_new (base, context->sock , EV_READ | EV_PERSIST, read_callback_dual_tor, context);
676
+ else
677
+ ev = event_new (base, context->sock , EV_READ | EV_PERSIST, read_callback, context);
678
+
583
679
if (ev == NULL ) {
584
680
syslog (LOG_ALERT, " event_new: failed to allocate memory for libevent event '%s'\n " , strerror (errno));
585
681
break ;
0 commit comments