func client() { ifaces, err := net.Interfaces() if err != nil { log.Printf("client: Can't enumerate interfaces? %v", err) return } addr, _, err := net.ParseCIDR("0.0.0.0/32") if err != nil { log.Printf("client: Can't parse to ip: %v", err) return } p := dhcp.RequestPacket(dhcp.Discover, ifaces[0].HardwareAddr, addr, []byte{1, 2, 3}, true, nil) fmt.Printf("client: %q\n", p) for { fmt.Printf("Try it\n") d, err := net.Dial("udp", "127.0.0.1:67") if err != nil { log.Printf("client: dial bad %v", err) } fmt.Printf("client: d is %q\n", d) ra, err := net.ResolveUDPAddr("udp", "127.0.0.1:67") if err != nil { log.Printf("client: ResolveUDPAddr failed: %v", err) return } fmt.Printf("client: ra %v\n", ra) if err := d.SetDeadline(time.Now().Add(10000 * time.Millisecond)); err != nil { log.Printf("client: Can't set deadline: %v\n", err) return } if _, err := d.Write(p); err != nil { log.Printf("client: WriteToUDP failed: %v", err) return } else { b := [512]byte{} if err := d.SetReadDeadline(time.Now().Add(10000 * time.Millisecond)); err != nil { log.Printf("client: Can't set deadline: %v\n", err) return } fmt.Printf("Client: sleep the read\n") time.Sleep(time.Second) if n, err := d.Read(b[:]); err != nil { log.Printf("client: Read from UDP failed: %v", err) continue } else { fmt.Printf("client: Data %v amt %v \n", b, n) return } } } }
func one(i net.Interface, r chan *dhcpInfo) { // the link has to be uppable if err := netlink.NetworkLinkUp(&i); err != nil { log.Printf("%v can't make it up: %v", i, err) return } addr, _, err := net.ParseCIDR("0.0.0.0/32") if err != nil { log.Printf("client: Can't parse to ip: %v", err) r <- nil return } // possibly bogus packet created. I think they are not creating an IP header. p := dhcp.RequestPacket(dhcp.Discover, i.HardwareAddr, addr, []byte{1, 2, 3}, false, nil) fmt.Printf("client: len %d\n", len(p)) u := &EtherIPUDPHeader{ Version: 4, IHL: 5, DPort: 67, SPort: 68, TotalLength: uint16(len(p)) + 20, Length: uint16(len(p)), DIP: 0xffffffff, Protocol: syscall.IPPROTO_UDP, TTL: 64, } raw := u.Marshal(p) /* goddamn. if only this had worked. s, err := syscall.LsfSocket(i.Index, syscall.ETH_P_IP) */ // yegads, the socket interface sucks so hard for over 30 years now ... // htons for a LOCAL RESOURCE? Riiiiiight. // How I miss Plan 9 s, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_DGRAM, 0x8) //syscall.ETH_P_IP) if err != nil { fmt.Printf("lsfsocket: got %v\n", err) r <- nil return } var lsall syscall.SockaddrLinklayer pp := (*[2]byte)(unsafe.Pointer(&lsall.Protocol)) pp[0] = 8 pp[1] = 0 lsall.Ifindex = i.Index lsall.Halen = 6 lsall.Addr = [8]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} if err = syscall.Bind(s, &lsall); err != nil { fmt.Printf("lsfsocket: bind got %v\n", err) r <- nil return } // we don't set family; Sendto does. bcast := &syscall.SockaddrLinklayer{ Protocol: 0x8, //syscall.ETH_P_IP, Ifindex: i.Index, Halen: 6, Addr: [8]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, } log.Printf("bcast is %v", bcast) for tries := 0; tries < 1; tries++ { fmt.Printf("Try it\n") err = syscall.Sendto(s, raw, 0, bcast) if err != nil { log.Printf("client: WriteToUDP failed: %v", err) r <- nil return } //log.Printf("wrote it; %v bytes", n) fmt.Printf("Client: sleep the read\n") time.Sleep(time.Second) b := [1024]byte{} for { n, sa, err := syscall.Recvfrom(s, b[:], 0) if err != nil { log.Printf("client: %v\n", err) r <- nil return } if n < 240 { continue } fmt.Printf("client: sa %v Data %v amt %v \n", sa, len(b[28:]), n) r <- &dhcpInfo{&i, dhcp.Packet(b[28:])} break } } close(r) //r <- nil }
func main() { if len(os.Args) != 3 { panic("not enough args") } intf, err := net.InterfaceByName(os.Args[1]) if err != nil { panic(err) } containerID := os.Args[2] log.Infof("Requesting for container ID %q on interface %q", containerID, intf.Name) contPid := getContainerInfo(containerID) log.Infof("Container has PID %s", contPid) runtime.LockOSThread() f, err := os.Open(fmt.Sprintf("/proc/%s/ns/net", contPid)) if err != nil { panic(err) } if _, _, err := unix.RawSyscall(unix.SYS_SETNS, f.Fd(), syscall.CLONE_NEWNET, 0); err != 0 { panic(err) } link, err := netlink.LinkByName("eth0") if err != nil { panic(err) } chaddr := link.Attrs().HardwareAddr p := dhcp.RequestPacket(dhcp.Discover, chaddr, nil, []byte{1, 2, 3, 4}, true, []dhcp.Option{}) conn, err := net.ListenPacket("udp", ":68") if err != nil { panic(err) } ipc := ipv4.NewPacketConn(conn) ipc.SetControlMessage(ipv4.FlagInterface, true) to := &net.UDPAddr{ IP: net.IPv4(255, 255, 255, 255), Port: 67, } eth0, err := net.InterfaceByName("eth0") if err != nil { panic(err) } if _, err := ipc.WriteTo(p, &ipv4.ControlMessage{IfIndex: eth0.Index}, to); err != nil { panic(err) } newPacket := dhcp.NewPacket(dhcp.BootReply) for { _, cm, _, err := ipc.ReadFrom(newPacket) if err != nil { panic(err) } if cm != nil && cm.IfIndex == eth0.Index { log.Infof("Received reply: %q", newPacket.YIAddr().String()) break } } addr, err := netlink.ParseAddr(newPacket.YIAddr().String() + "/16") if err != nil { panic(err) } log.Infof("Setting interface eth0...") if err := netlink.AddrAdd(link, addr); err != nil { panic(err) } }