@@ -14,13 +14,14 @@ use network_types::{
1414 arp:: ArpHdr ,
1515 eth:: { EthHdr , EtherType } ,
1616 icmp:: { Icmp , IcmpHdr , IcmpV6Hdr } ,
17+ igmp:: { IGMPv1Hdr , IGMPv2Hdr , IGMPv3MembershipQueryHdr , IGMPv3MembershipReportHdr } ,
1718 ip:: { IpHdr , IpProto , Ipv4Hdr , Ipv6Hdr } ,
1819 sctp:: SctpHdr ,
1920 tcp:: TcpHdr ,
2021 udp:: UdpHdr ,
2122} ;
2223use oryx_common:: {
23- MAX_FIREWALL_RULES , MAX_RULES_PORT , ProtoHdr , RawData , RawFrame , RawPacket ,
24+ IGMPv3Hdr , IgmpHdr , MAX_FIREWALL_RULES , MAX_RULES_PORT , ProtoHdr , RawData , RawFrame , RawPacket ,
2425 protocols:: { LinkProtocol , NetworkProtocol , Protocol , TransportProtocol } ,
2526} ;
2627
@@ -304,6 +305,140 @@ fn process(ctx: TcContext) -> Result<i32, ()> {
304305 } ) ;
305306 }
306307 }
308+
309+ IpProto :: Igmp => {
310+ if filter_packet ( Protocol :: Network ( NetworkProtocol :: Igmp ) ) {
311+ return Ok ( TC_ACT_PIPE ) ;
312+ }
313+
314+ let payload_length = unsafe {
315+ u16:: from_be_bytes ( ( * ipv4_header) . tot_len ) - ( * ipv4_header) . ihl ( ) as u16
316+ } ;
317+
318+ let ihl: u8 = ctx. load ( EthHdr :: LEN ) . map_err ( |_| ( ) ) ?;
319+ let ihl = ( ihl & 0x0F ) * 4 ;
320+
321+ let igmp_type: u8 = ctx. load ( EthHdr :: LEN + ihl as usize ) . map_err ( |_| ( ) ) ?;
322+
323+ match igmp_type {
324+ 0x11 => {
325+ if payload_length == 8 {
326+ // v1 or v2
327+ let max_response_time: u8 =
328+ ctx. load ( EthHdr :: LEN + ihl as usize + 1 ) . map_err ( |_| ( ) ) ?;
329+
330+ if max_response_time == 0 {
331+ //v1
332+ let igmp_header: * const IGMPv1Hdr =
333+ ptr_at ( & ctx, EthHdr :: LEN + ihl as usize ) ?;
334+
335+ unsafe {
336+ submit ( RawData {
337+ frame : RawFrame {
338+ header : * eth_header,
339+ payload : RawPacket :: Ip (
340+ IpHdr :: V4 ( * ipv4_header) ,
341+ ProtoHdr :: Igmp ( IgmpHdr :: V1 ( * igmp_header) ) ,
342+ ) ,
343+ } ,
344+ pid,
345+ } ) ;
346+ }
347+ } else {
348+ // v2
349+ let igmp_header: * const IGMPv2Hdr =
350+ ptr_at ( & ctx, EthHdr :: LEN + ihl as usize ) ?;
351+
352+ unsafe {
353+ submit ( RawData {
354+ frame : RawFrame {
355+ header : * eth_header,
356+ payload : RawPacket :: Ip (
357+ IpHdr :: V4 ( * ipv4_header) ,
358+ ProtoHdr :: Igmp ( IgmpHdr :: V2 ( * igmp_header) ) ,
359+ ) ,
360+ } ,
361+ pid,
362+ } ) ;
363+ }
364+ }
365+ } else {
366+ // v3
367+ let igmp_header: * const IGMPv3MembershipQueryHdr =
368+ ptr_at ( & ctx, EthHdr :: LEN + ihl as usize ) ?;
369+
370+ unsafe {
371+ submit ( RawData {
372+ frame : RawFrame {
373+ header : * eth_header,
374+ payload : RawPacket :: Ip (
375+ IpHdr :: V4 ( * ipv4_header) ,
376+ ProtoHdr :: Igmp ( IgmpHdr :: V3 ( IGMPv3Hdr :: Query (
377+ * igmp_header,
378+ ) ) ) ,
379+ ) ,
380+ } ,
381+ pid,
382+ } ) ;
383+ }
384+ }
385+ }
386+ 0x12 => {
387+ let igmp_header: * const IGMPv1Hdr =
388+ ptr_at ( & ctx, EthHdr :: LEN + ihl as usize ) ?;
389+
390+ unsafe {
391+ submit ( RawData {
392+ frame : RawFrame {
393+ header : * eth_header,
394+ payload : RawPacket :: Ip (
395+ IpHdr :: V4 ( * ipv4_header) ,
396+ ProtoHdr :: Igmp ( IgmpHdr :: V1 ( * igmp_header) ) ,
397+ ) ,
398+ } ,
399+ pid,
400+ } ) ;
401+ }
402+ }
403+ 0x16 | 0x17 => {
404+ let igmp_header: * const IGMPv2Hdr =
405+ ptr_at ( & ctx, EthHdr :: LEN + ihl as usize ) ?;
406+
407+ unsafe {
408+ submit ( RawData {
409+ frame : RawFrame {
410+ header : * eth_header,
411+ payload : RawPacket :: Ip (
412+ IpHdr :: V4 ( * ipv4_header) ,
413+ ProtoHdr :: Igmp ( IgmpHdr :: V2 ( * igmp_header) ) ,
414+ ) ,
415+ } ,
416+ pid,
417+ } ) ;
418+ }
419+ }
420+ 0x22 => {
421+ let igmp_header: * const IGMPv3MembershipReportHdr =
422+ ptr_at ( & ctx, EthHdr :: LEN + ihl as usize ) ?;
423+
424+ unsafe {
425+ submit ( RawData {
426+ frame : RawFrame {
427+ header : * eth_header,
428+ payload : RawPacket :: Ip (
429+ IpHdr :: V4 ( * ipv4_header) ,
430+ ProtoHdr :: Igmp ( IgmpHdr :: V3 ( IGMPv3Hdr :: Report (
431+ * igmp_header,
432+ ) ) ) ,
433+ ) ,
434+ } ,
435+ pid,
436+ } ) ;
437+ }
438+ }
439+ _ => { }
440+ }
441+ }
307442 _ => { }
308443 }
309444 }
0 commit comments