github.com/sagernet/netlink@v0.0.0-20240612041022-b9a21c07ac6a/gtp_linux.go (about)

     1  package netlink
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"strings"
     7  	"syscall"
     8  
     9  	"github.com/sagernet/netlink/nl"
    10  	"golang.org/x/sys/unix"
    11  )
    12  
    13  type PDP struct {
    14  	Version     uint32
    15  	TID         uint64
    16  	PeerAddress net.IP
    17  	MSAddress   net.IP
    18  	Flow        uint16
    19  	NetNSFD     uint32
    20  	ITEI        uint32
    21  	OTEI        uint32
    22  }
    23  
    24  func (pdp *PDP) String() string {
    25  	elems := []string{}
    26  	elems = append(elems, fmt.Sprintf("Version: %d", pdp.Version))
    27  	if pdp.Version == 0 {
    28  		elems = append(elems, fmt.Sprintf("TID: %d", pdp.TID))
    29  	} else if pdp.Version == 1 {
    30  		elems = append(elems, fmt.Sprintf("TEI: %d/%d", pdp.ITEI, pdp.OTEI))
    31  	}
    32  	elems = append(elems, fmt.Sprintf("MS-Address: %s", pdp.MSAddress))
    33  	elems = append(elems, fmt.Sprintf("Peer-Address: %s", pdp.PeerAddress))
    34  	return fmt.Sprintf("{%s}", strings.Join(elems, " "))
    35  }
    36  
    37  func (p *PDP) parseAttributes(attrs []syscall.NetlinkRouteAttr) error {
    38  	for _, a := range attrs {
    39  		switch a.Attr.Type {
    40  		case nl.GENL_GTP_ATTR_VERSION:
    41  			p.Version = native.Uint32(a.Value)
    42  		case nl.GENL_GTP_ATTR_TID:
    43  			p.TID = native.Uint64(a.Value)
    44  		case nl.GENL_GTP_ATTR_PEER_ADDRESS:
    45  			p.PeerAddress = net.IP(a.Value)
    46  		case nl.GENL_GTP_ATTR_MS_ADDRESS:
    47  			p.MSAddress = net.IP(a.Value)
    48  		case nl.GENL_GTP_ATTR_FLOW:
    49  			p.Flow = native.Uint16(a.Value)
    50  		case nl.GENL_GTP_ATTR_NET_NS_FD:
    51  			p.NetNSFD = native.Uint32(a.Value)
    52  		case nl.GENL_GTP_ATTR_I_TEI:
    53  			p.ITEI = native.Uint32(a.Value)
    54  		case nl.GENL_GTP_ATTR_O_TEI:
    55  			p.OTEI = native.Uint32(a.Value)
    56  		}
    57  	}
    58  	return nil
    59  }
    60  
    61  func parsePDP(msgs [][]byte) ([]*PDP, error) {
    62  	pdps := make([]*PDP, 0, len(msgs))
    63  	for _, m := range msgs {
    64  		attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
    65  		if err != nil {
    66  			return nil, err
    67  		}
    68  		pdp := &PDP{}
    69  		if err := pdp.parseAttributes(attrs); err != nil {
    70  			return nil, err
    71  		}
    72  		pdps = append(pdps, pdp)
    73  	}
    74  	return pdps, nil
    75  }
    76  
    77  func (h *Handle) GTPPDPList() ([]*PDP, error) {
    78  	f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  	msg := &nl.Genlmsg{
    83  		Command: nl.GENL_GTP_CMD_GETPDP,
    84  		Version: nl.GENL_GTP_VERSION,
    85  	}
    86  	req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_DUMP)
    87  	req.AddData(msg)
    88  	msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  	return parsePDP(msgs)
    93  }
    94  
    95  func GTPPDPList() ([]*PDP, error) {
    96  	return pkgHandle.GTPPDPList()
    97  }
    98  
    99  func gtpPDPGet(req *nl.NetlinkRequest) (*PDP, error) {
   100  	msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  	pdps, err := parsePDP(msgs)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  	if len(pdps) != 1 {
   109  		return nil, fmt.Errorf("invalid reqponse for GENL_GTP_CMD_GETPDP")
   110  	}
   111  	return pdps[0], nil
   112  }
   113  
   114  func (h *Handle) GTPPDPByTID(link Link, tid int) (*PDP, error) {
   115  	f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	msg := &nl.Genlmsg{
   120  		Command: nl.GENL_GTP_CMD_GETPDP,
   121  		Version: nl.GENL_GTP_VERSION,
   122  	}
   123  	req := h.newNetlinkRequest(int(f.ID), 0)
   124  	req.AddData(msg)
   125  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(0)))
   126  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
   127  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_TID, nl.Uint64Attr(uint64(tid))))
   128  	return gtpPDPGet(req)
   129  }
   130  
   131  func GTPPDPByTID(link Link, tid int) (*PDP, error) {
   132  	return pkgHandle.GTPPDPByTID(link, tid)
   133  }
   134  
   135  func (h *Handle) GTPPDPByITEI(link Link, itei int) (*PDP, error) {
   136  	f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  	msg := &nl.Genlmsg{
   141  		Command: nl.GENL_GTP_CMD_GETPDP,
   142  		Version: nl.GENL_GTP_VERSION,
   143  	}
   144  	req := h.newNetlinkRequest(int(f.ID), 0)
   145  	req.AddData(msg)
   146  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(1)))
   147  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
   148  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_I_TEI, nl.Uint32Attr(uint32(itei))))
   149  	return gtpPDPGet(req)
   150  }
   151  
   152  func GTPPDPByITEI(link Link, itei int) (*PDP, error) {
   153  	return pkgHandle.GTPPDPByITEI(link, itei)
   154  }
   155  
   156  func (h *Handle) GTPPDPByMSAddress(link Link, addr net.IP) (*PDP, error) {
   157  	f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  	msg := &nl.Genlmsg{
   162  		Command: nl.GENL_GTP_CMD_GETPDP,
   163  		Version: nl.GENL_GTP_VERSION,
   164  	}
   165  	req := h.newNetlinkRequest(int(f.ID), 0)
   166  	req.AddData(msg)
   167  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(0)))
   168  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
   169  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_MS_ADDRESS, []byte(addr.To4())))
   170  	return gtpPDPGet(req)
   171  }
   172  
   173  func GTPPDPByMSAddress(link Link, addr net.IP) (*PDP, error) {
   174  	return pkgHandle.GTPPDPByMSAddress(link, addr)
   175  }
   176  
   177  func (h *Handle) GTPPDPAdd(link Link, pdp *PDP) error {
   178  	f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
   179  	if err != nil {
   180  		return err
   181  	}
   182  	msg := &nl.Genlmsg{
   183  		Command: nl.GENL_GTP_CMD_NEWPDP,
   184  		Version: nl.GENL_GTP_VERSION,
   185  	}
   186  	req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_EXCL|unix.NLM_F_ACK)
   187  	req.AddData(msg)
   188  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version)))
   189  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
   190  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_PEER_ADDRESS, []byte(pdp.PeerAddress.To4())))
   191  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_MS_ADDRESS, []byte(pdp.MSAddress.To4())))
   192  
   193  	switch pdp.Version {
   194  	case 0:
   195  		req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_TID, nl.Uint64Attr(pdp.TID)))
   196  		req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_FLOW, nl.Uint16Attr(pdp.Flow)))
   197  	case 1:
   198  		req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_I_TEI, nl.Uint32Attr(pdp.ITEI)))
   199  		req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_O_TEI, nl.Uint32Attr(pdp.OTEI)))
   200  	default:
   201  		return fmt.Errorf("unsupported GTP version: %d", pdp.Version)
   202  	}
   203  	_, err = req.Execute(unix.NETLINK_GENERIC, 0)
   204  	return err
   205  }
   206  
   207  func GTPPDPAdd(link Link, pdp *PDP) error {
   208  	return pkgHandle.GTPPDPAdd(link, pdp)
   209  }
   210  
   211  func (h *Handle) GTPPDPDel(link Link, pdp *PDP) error {
   212  	f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
   213  	if err != nil {
   214  		return err
   215  	}
   216  	msg := &nl.Genlmsg{
   217  		Command: nl.GENL_GTP_CMD_DELPDP,
   218  		Version: nl.GENL_GTP_VERSION,
   219  	}
   220  	req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_EXCL|unix.NLM_F_ACK)
   221  	req.AddData(msg)
   222  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version)))
   223  	req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
   224  
   225  	switch pdp.Version {
   226  	case 0:
   227  		req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_TID, nl.Uint64Attr(pdp.TID)))
   228  	case 1:
   229  		req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_I_TEI, nl.Uint32Attr(pdp.ITEI)))
   230  	default:
   231  		return fmt.Errorf("unsupported GTP version: %d", pdp.Version)
   232  	}
   233  	_, err = req.Execute(unix.NETLINK_GENERIC, 0)
   234  	return err
   235  }
   236  
   237  func GTPPDPDel(link Link, pdp *PDP) error {
   238  	return pkgHandle.GTPPDPDel(link, pdp)
   239  }