123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- package netlink
- import (
- "fmt"
- "net"
- "strings"
- "syscall"
- "github.com/vishvananda/netlink/nl"
- )
- type PDP struct {
- Version uint32
- TID uint64
- PeerAddress net.IP
- MSAddress net.IP
- Flow uint16
- NetNSFD uint32
- ITEI uint32
- OTEI uint32
- }
- func (pdp *PDP) String() string {
- elems := []string{}
- elems = append(elems, fmt.Sprintf("Version: %d", pdp.Version))
- if pdp.Version == 0 {
- elems = append(elems, fmt.Sprintf("TID: %d", pdp.TID))
- } else if pdp.Version == 1 {
- elems = append(elems, fmt.Sprintf("TEI: %d/%d", pdp.ITEI, pdp.OTEI))
- }
- elems = append(elems, fmt.Sprintf("MS-Address: %s", pdp.MSAddress))
- elems = append(elems, fmt.Sprintf("Peer-Address: %s", pdp.PeerAddress))
- return fmt.Sprintf("{%s}", strings.Join(elems, " "))
- }
- func (p *PDP) parseAttributes(attrs []syscall.NetlinkRouteAttr) error {
- for _, a := range attrs {
- switch a.Attr.Type {
- case nl.GENL_GTP_ATTR_VERSION:
- p.Version = native.Uint32(a.Value)
- case nl.GENL_GTP_ATTR_TID:
- p.TID = native.Uint64(a.Value)
- case nl.GENL_GTP_ATTR_PEER_ADDRESS:
- p.PeerAddress = net.IP(a.Value)
- case nl.GENL_GTP_ATTR_MS_ADDRESS:
- p.MSAddress = net.IP(a.Value)
- case nl.GENL_GTP_ATTR_FLOW:
- p.Flow = native.Uint16(a.Value)
- case nl.GENL_GTP_ATTR_NET_NS_FD:
- p.NetNSFD = native.Uint32(a.Value)
- case nl.GENL_GTP_ATTR_I_TEI:
- p.ITEI = native.Uint32(a.Value)
- case nl.GENL_GTP_ATTR_O_TEI:
- p.OTEI = native.Uint32(a.Value)
- }
- }
- return nil
- }
- func parsePDP(msgs [][]byte) ([]*PDP, error) {
- pdps := make([]*PDP, 0, len(msgs))
- for _, m := range msgs {
- attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
- if err != nil {
- return nil, err
- }
- pdp := &PDP{}
- if err := pdp.parseAttributes(attrs); err != nil {
- return nil, err
- }
- pdps = append(pdps, pdp)
- }
- return pdps, nil
- }
- func (h *Handle) GTPPDPList() ([]*PDP, error) {
- f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
- if err != nil {
- return nil, err
- }
- msg := &nl.Genlmsg{
- Command: nl.GENL_GTP_CMD_GETPDP,
- Version: nl.GENL_GTP_VERSION,
- }
- req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_DUMP)
- req.AddData(msg)
- msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
- if err != nil {
- return nil, err
- }
- return parsePDP(msgs)
- }
- func GTPPDPList() ([]*PDP, error) {
- return pkgHandle.GTPPDPList()
- }
- func gtpPDPGet(req *nl.NetlinkRequest) (*PDP, error) {
- msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
- if err != nil {
- return nil, err
- }
- pdps, err := parsePDP(msgs)
- if err != nil {
- return nil, err
- }
- if len(pdps) != 1 {
- return nil, fmt.Errorf("invalid reqponse for GENL_GTP_CMD_GETPDP")
- }
- return pdps[0], nil
- }
- func (h *Handle) GTPPDPByTID(link Link, tid int) (*PDP, error) {
- f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
- if err != nil {
- return nil, err
- }
- msg := &nl.Genlmsg{
- Command: nl.GENL_GTP_CMD_GETPDP,
- Version: nl.GENL_GTP_VERSION,
- }
- req := h.newNetlinkRequest(int(f.ID), 0)
- req.AddData(msg)
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(0)))
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_TID, nl.Uint64Attr(uint64(tid))))
- return gtpPDPGet(req)
- }
- func GTPPDPByTID(link Link, tid int) (*PDP, error) {
- return pkgHandle.GTPPDPByTID(link, tid)
- }
- func (h *Handle) GTPPDPByITEI(link Link, itei int) (*PDP, error) {
- f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
- if err != nil {
- return nil, err
- }
- msg := &nl.Genlmsg{
- Command: nl.GENL_GTP_CMD_GETPDP,
- Version: nl.GENL_GTP_VERSION,
- }
- req := h.newNetlinkRequest(int(f.ID), 0)
- req.AddData(msg)
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(1)))
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_I_TEI, nl.Uint32Attr(uint32(itei))))
- return gtpPDPGet(req)
- }
- func GTPPDPByITEI(link Link, itei int) (*PDP, error) {
- return pkgHandle.GTPPDPByITEI(link, itei)
- }
- func (h *Handle) GTPPDPByMSAddress(link Link, addr net.IP) (*PDP, error) {
- f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
- if err != nil {
- return nil, err
- }
- msg := &nl.Genlmsg{
- Command: nl.GENL_GTP_CMD_GETPDP,
- Version: nl.GENL_GTP_VERSION,
- }
- req := h.newNetlinkRequest(int(f.ID), 0)
- req.AddData(msg)
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(0)))
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_MS_ADDRESS, []byte(addr.To4())))
- return gtpPDPGet(req)
- }
- func GTPPDPByMSAddress(link Link, addr net.IP) (*PDP, error) {
- return pkgHandle.GTPPDPByMSAddress(link, addr)
- }
- func (h *Handle) GTPPDPAdd(link Link, pdp *PDP) error {
- f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
- if err != nil {
- return err
- }
- msg := &nl.Genlmsg{
- Command: nl.GENL_GTP_CMD_NEWPDP,
- Version: nl.GENL_GTP_VERSION,
- }
- req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
- req.AddData(msg)
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version)))
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_PEER_ADDRESS, []byte(pdp.PeerAddress.To4())))
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_MS_ADDRESS, []byte(pdp.MSAddress.To4())))
- switch pdp.Version {
- case 0:
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_TID, nl.Uint64Attr(pdp.TID)))
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_FLOW, nl.Uint16Attr(pdp.Flow)))
- case 1:
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_I_TEI, nl.Uint32Attr(pdp.ITEI)))
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_O_TEI, nl.Uint32Attr(pdp.OTEI)))
- default:
- return fmt.Errorf("unsupported GTP version: %d", pdp.Version)
- }
- _, err = req.Execute(syscall.NETLINK_GENERIC, 0)
- return err
- }
- func GTPPDPAdd(link Link, pdp *PDP) error {
- return pkgHandle.GTPPDPAdd(link, pdp)
- }
- func (h *Handle) GTPPDPDel(link Link, pdp *PDP) error {
- f, err := h.GenlFamilyGet(nl.GENL_GTP_NAME)
- if err != nil {
- return err
- }
- msg := &nl.Genlmsg{
- Command: nl.GENL_GTP_CMD_DELPDP,
- Version: nl.GENL_GTP_VERSION,
- }
- req := h.newNetlinkRequest(int(f.ID), syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
- req.AddData(msg)
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_VERSION, nl.Uint32Attr(pdp.Version)))
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_LINK, nl.Uint32Attr(uint32(link.Attrs().Index))))
- switch pdp.Version {
- case 0:
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_TID, nl.Uint64Attr(pdp.TID)))
- case 1:
- req.AddData(nl.NewRtAttr(nl.GENL_GTP_ATTR_I_TEI, nl.Uint32Attr(pdp.ITEI)))
- default:
- return fmt.Errorf("unsupported GTP version: %d", pdp.Version)
- }
- _, err = req.Execute(syscall.NETLINK_GENERIC, 0)
- return err
- }
- func GTPPDPDel(link Link, pdp *PDP) error {
- return pkgHandle.GTPPDPDel(link, pdp)
- }
|