diff --git a/netlink/netlink_linux.go b/netlink/netlink_linux.go index b16dec0..1f48a64 100644 --- a/netlink/netlink_linux.go +++ b/netlink/netlink_linux.go @@ -15,7 +15,8 @@ const ( DEFAULT_CHANGE = 0xFFFFFFFF IFLA_INFO_KIND = 1 IFLA_INFO_DATA = 2 - VETH_PEER = 1 + VETH_INFO_PEER = 1 + IFLA_NET_NS_FD = 28 ) var nextSeqNr int @@ -397,6 +398,28 @@ func NetworkLinkUp(iface *net.Interface) error { return s.HandleAck(wb.Seq) } +func NetworkLinkDown(iface *net.Interface) error { + s, err := getNetlinkSocket() + if err != nil { + return err + } + defer s.Close() + + wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_ACK) + + msg := newIfInfomsg(syscall.AF_UNSPEC) + msg.Change = syscall.IFF_UP + msg.Flags = 0 & ^syscall.IFF_UP + msg.Index = int32(iface.Index) + wb.AddData(msg) + + if err := s.Send(wb); err != nil { + return err + } + + return s.HandleAck(wb.Seq) +} + func NetworkSetMTU(iface *net.Interface, mtu int) error { s, err := getNetlinkSocket() if err != nil { @@ -493,6 +516,38 @@ func NetworkSetNsPid(iface *net.Interface, nspid int) error { return s.HandleAck(wb.Seq) } +func NetworkSetNsFd(iface *net.Interface, fd int) error { + s, err := getNetlinkSocket() + if err != nil { + return err + } + defer s.Close() + + wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK) + + msg := newIfInfomsg(syscall.AF_UNSPEC) + msg.Type = syscall.RTM_SETLINK + msg.Flags = syscall.NLM_F_REQUEST + msg.Index = int32(iface.Index) + msg.Change = DEFAULT_CHANGE + wb.AddData(msg) + + var ( + b = make([]byte, 4) + native = nativeEndian() + ) + native.PutUint32(b, uint32(fd)) + + data := newRtAttr(IFLA_NET_NS_FD, b) + wb.AddData(data) + + if err := s.Send(wb); err != nil { + return err + } + + return s.HandleAck(wb.Seq) +} + // Add an Ip address to an interface. This is identical to: // ip addr add $ip/$ipNet dev $iface func NetworkLinkAddIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error { @@ -695,7 +750,7 @@ func getIfSocket() (fd int, err error) { return -1, err } -func NetworkChangeName(oldName, newName string) error { +func NetworkChangeName(iface *net.Interface, newName string) error { fd, err := getIfSocket() if err != nil { return err @@ -703,7 +758,9 @@ func NetworkChangeName(oldName, newName string) error { defer syscall.Close(fd) data := [IFNAMSIZ * 2]byte{} - copy(data[:IFNAMSIZ-1], oldName) + // the "-1"s here are very important for ensuring we get proper null + // termination of our new C strings + copy(data[:IFNAMSIZ-1], iface.Name) copy(data[IFNAMSIZ:IFNAMSIZ*2-1], newName) if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.SIOCSIFNAME, uintptr(unsafe.Pointer(&data[0]))); errno != 0 { @@ -730,7 +787,7 @@ func NetworkCreateVethPair(name1, name2 string) error { nest1 := newRtAttr(syscall.IFLA_LINKINFO, nil) newRtAttrChild(nest1, IFLA_INFO_KIND, zeroTerminated("veth")) nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil) - nest3 := newRtAttrChild(nest2, VETH_PEER, nil) + nest3 := newRtAttrChild(nest2, VETH_INFO_PEER, nil) last := newRtAttrChild(nest3, syscall.IFLA_IFNAME, zeroTerminated(name2)) last.prefix = syscall.SizeofIfInfomsg