github.com/20yyq/packet@v0.1.4-0.20231013092308-386a004a3baa/netlink.go (about)

     1  // @@
     2  // @ Author       : Eacher
     3  // @ Date         : 2023-07-01 15:20:41
     4  // @ LastEditTime : 2023-09-20 09:44:57
     5  // @ LastEditors  : Eacher
     6  // @ --------------------------------------------------------------------------------<
     7  // @ Description  : 
     8  // @ --------------------------------------------------------------------------------<
     9  // @ FilePath     : /20yyq/packet/netlink.go
    10  // @@
    11  package packet
    12  
    13  import (
    14  	"unsafe"
    15  	"syscall"
    16  )
    17  
    18  const (
    19  	SizeofNlMsghdr 	= syscall.SizeofNlMsghdr
    20  	SizeofNlAttr 	= syscall.SizeofNlAttr
    21  	SizeofRtAttr 	= syscall.SizeofRtAttr
    22  	SizeofNlMsgerr 	= syscall.SizeofNlMsgerr
    23  	SizeofIfAddrmsg = syscall.SizeofIfAddrmsg
    24  	SizeofRtMsg 	= syscall.SizeofRtMsg
    25  	SizeofIfInfomsg = syscall.SizeofIfInfomsg
    26  )
    27  
    28  type IfInfomsg syscall.IfInfomsg
    29  type IfAddrmsg syscall.IfAddrmsg
    30  type RtMsg syscall.RtMsg
    31  type NlMsghdr syscall.NlMsghdr
    32  type NlMsgerr struct {
    33  	Error int32
    34  	Msg   NlMsghdr
    35  }
    36  type NetlinkMessage struct {
    37  	Header *NlMsghdr
    38  	Data   []byte
    39  }
    40  type RtAttr struct {
    41  	*syscall.RtAttr
    42  	Data   []byte
    43  }
    44  type NlAttr struct {
    45  	*syscall.NlAttr
    46  	Data   []byte
    47  }
    48  
    49  //go:linkname nlmAlignOf syscall.nlmAlignOf
    50  func nlmAlignOf(msglen int) int
    51  
    52  //go:linkname rtaAlignOf syscall.rtaAlignOf
    53  func rtaAlignOf(attrlen int) int
    54  
    55  func NewIfInfomsg(b [SizeofIfInfomsg]byte) (info *IfInfomsg) {
    56  	info = (*IfInfomsg)(unsafe.Pointer(&b[0]))
    57  	return
    58  }
    59  
    60  func (info IfInfomsg) WireFormat() []byte {
    61  	var b [SizeofIfInfomsg]byte
    62  	b[0], b[1] = info.Family, info.X__ifi_pad
    63  	*(*uint16)(unsafe.Pointer(&b[2])) = info.Type
    64  	*(*int32)(unsafe.Pointer(&b[4])) = info.Index
    65  	*(*uint32)(unsafe.Pointer(&b[8])) = info.Flags
    66  	*(*uint32)(unsafe.Pointer(&b[12])) = info.Change
    67  	return b[:]
    68  }
    69  
    70  func NewIfAddrmsg(b [SizeofIfAddrmsg]byte) (addr *IfAddrmsg) {
    71  	addr = (*IfAddrmsg)(unsafe.Pointer(&b[0]))
    72  	return
    73  }
    74  
    75  func (addr IfAddrmsg) WireFormat() []byte {
    76  	var b [SizeofIfAddrmsg]byte
    77  	b[0], b[1], b[2], b[3] = addr.Family, addr.Prefixlen, addr.Flags, addr.Scope
    78  	*(*uint32)(unsafe.Pointer(&b[4])) = addr.Index
    79  	return b[:]
    80  }
    81  
    82  func NewRtMsg(b [SizeofRtMsg]byte) (rtmsg *RtMsg) {
    83  	rtmsg = (*RtMsg)(unsafe.Pointer(&b[0]))
    84  	return
    85  }
    86  
    87  func (rtmsg RtMsg) WireFormat() []byte {
    88  	var b [SizeofRtMsg]byte
    89  	b[0], b[1], b[2], b[3] = rtmsg.Family, rtmsg.Dst_len, rtmsg.Src_len, rtmsg.Tos
    90  	b[4], b[5], b[6], b[7] = rtmsg.Table, rtmsg.Protocol, rtmsg.Scope, rtmsg.Type
    91  	*(*uint32)(unsafe.Pointer(&b[8])) = rtmsg.Flags
    92  	return b[:]
    93  }
    94  
    95  func NewNlMsghdr(b [SizeofNlMsghdr]byte) (hdr *NlMsghdr) {
    96  	hdr = (*NlMsghdr)(unsafe.Pointer(&b[0]))
    97  	return
    98  }
    99  
   100  func (hdr NlMsghdr) WireFormat() []byte {
   101  	var b [SizeofNlMsghdr]byte
   102  	hdr.WireFormatToByte(&b)
   103  	return b[:]
   104  }
   105  
   106  func (hdr NlMsghdr) WireFormatToByte(b *[SizeofNlMsghdr]byte) {
   107  	*(*uint32)(unsafe.Pointer(&b[0])) = hdr.Len
   108  	*(*uint16)(unsafe.Pointer(&b[4])) = hdr.Type
   109  	*(*uint16)(unsafe.Pointer(&b[6])) = hdr.Flags
   110  	*(*uint32)(unsafe.Pointer(&b[8])) = hdr.Seq
   111  	*(*uint32)(unsafe.Pointer(&b[12])) = hdr.Pid
   112  }
   113  
   114  func NewNlMsgerr(b [SizeofNlMsgerr]byte) (nlmsge *NlMsgerr) {
   115  	nlmsge = (*NlMsgerr)(unsafe.Pointer(&b[0]))
   116  	return
   117  }
   118  
   119  func (nlmsge NlMsgerr) WireFormat() []byte {
   120  	var b [SizeofNlMsgerr]byte
   121  	*(*int32)(unsafe.Pointer(&b[0])) = nlmsge.Error
   122  	nlmsge.Msg.WireFormatToByte((*[SizeofNlMsghdr]byte)(b[4:]))
   123  	return b[:]
   124  }
   125  
   126  func NewNetlinkMessage(b []byte) (nlmsg []*NetlinkMessage) {
   127  	for len(b) >= SizeofNlMsghdr {
   128  		m := &NetlinkMessage{Header: NewNlMsghdr(([SizeofNlMsghdr]byte)(b))}
   129  		l := nlmAlignOf(int(m.Header.Len))
   130  		if m.Header.Len < SizeofNlMsghdr || l > len(b) {
   131  			break
   132  		}
   133  		if int(m.Header.Len - SizeofNlMsghdr) < len(b) {
   134  			m.Data = b[SizeofNlMsghdr:m.Header.Len]
   135  		} else {
   136  			m.Data = b[SizeofNlMsghdr:]
   137  		}
   138  		b = b[l:]
   139  		nlmsg = append(nlmsg, m)
   140  	}
   141  	return
   142  }
   143  
   144  func (nlmsg NetlinkMessage) WireFormat() []byte {
   145  	b := make([]byte, SizeofNlMsghdr + len(nlmsg.Data))
   146  	copy(b, nlmsg.Header.WireFormat())
   147  	copy(b[SizeofNlMsghdr:], nlmsg.Data)
   148  	return b
   149  }
   150  
   151  // ParseNetlinkRouteAttr parses m's payload as an array of netlink
   152  // route attributes and returns the slice containing the
   153  // NetlinkRouteAttr structures.
   154  func ParseNetlinkRouteAttr(m *NetlinkMessage) ([]*RtAttr, error) {
   155  	var b []byte
   156  	switch m.Header.Type {
   157  	case syscall.RTM_NEWLINK, syscall.RTM_DELLINK:
   158  		b = m.Data[SizeofIfInfomsg:]
   159  	case syscall.RTM_NEWADDR, syscall.RTM_DELADDR:
   160  		b = m.Data[SizeofIfAddrmsg:]
   161  	case syscall.RTM_NEWROUTE, syscall.RTM_DELROUTE:
   162  		b = m.Data[SizeofRtMsg:]
   163  	default:
   164  		return nil, syscall.EINVAL
   165  	}
   166  	return NewRtAttrs(b), nil
   167  }
   168  
   169  func NewRtAttrs(b []byte) []*RtAttr {
   170  	var attrs []*RtAttr
   171  	for len(b) >= SizeofRtAttr {
   172  		r := (*syscall.RtAttr)(unsafe.Pointer(&b[0]))
   173  		if int(r.Len) < SizeofRtAttr || int(r.Len) > len(b) {
   174  			break
   175  		}
   176  		attrs = append(attrs, &RtAttr{RtAttr: r, Data: b[SizeofRtAttr:r.Len]})
   177  		b = b[rtaAlignOf(int(r.Len)):]
   178  	}
   179  	return attrs
   180  }
   181  
   182  func (rta RtAttr) WireFormat() []byte {
   183  	b := make([]byte, SizeofRtAttr + len(rta.Data))
   184  	*(*uint16)(unsafe.Pointer(&b[0])) = rta.Len
   185  	*(*uint16)(unsafe.Pointer(&b[2])) = rta.Type
   186  	copy(b[SizeofRtAttr:], rta.Data)
   187  	return b
   188  }
   189  
   190  func NewNlAttrs(b []byte) []*NlAttr {
   191  	var attrs []*NlAttr
   192  	for len(b) >= SizeofNlAttr {
   193  		nl := (*syscall.NlAttr)(unsafe.Pointer(&b[0]))
   194  		if int(nl.Len) < SizeofNlAttr || int(nl.Len) > len(b) {
   195  			break
   196  		}
   197  		attrs = append(attrs, &NlAttr{NlAttr: nl, Data: b[SizeofNlAttr:nl.Len]})
   198  		b = b[rtaAlignOf(int(nl.Len)):]
   199  	}
   200  	return attrs
   201  }
   202  
   203  func (nla NlAttr) WireFormat() []byte {
   204  	b := make([]byte, SizeofNlAttr + len(nla.Data))
   205  	*(*uint16)(unsafe.Pointer(&b[0])) = nla.Len
   206  	*(*uint16)(unsafe.Pointer(&b[2])) = nla.Type
   207  	copy(b[SizeofNlAttr:], nla.Data)
   208  	return b
   209  }