func main() { var err error // Loading of the parameters getParameters() database, err = sql.Open("sqlite3", "mysqlite_3") if err != nil { log.Fatal(err) } defer database.Close() initDB() handler := func(data []byte) { pkg := dhcpPacket.NewDhcpPacket() dhcpPacket.ParseDhcpPacket(data, pkg) if pkg.GetMessageType() == 1 { response(pkg) } else if pkg.GetMessageType() == 3 { ack(pkg) } else if pkg.GetMessageType() == 7 { release(pkg) } } dhcpUDP.InitListener(handler) }
func response(request *dhcpPacket.DhcpPacket) { var err error packet_response := dhcpPacket.NewDhcpPacket() // Fixed part in the body packet_response.SetOp(2) packet_response.SetCiaddr("0.0.0.0") packet_response.SetSiaddr(parameters.IP_server) packet_response.SetGiaddr("0.0.0.0") // Fixed part in the options packet_response.SetDhcpServer(parameters.IP_server) packet_response.SetLeaseTime(parameters.Allocation_time) packet_response.SetSubnetMask(parameters.Netmask) packet_response.SetDnsServer([]string{parameters.IP_DNS}) packet_response.SetRouter(parameters.IP_server) // Specific response to the client request packet_response.SetXid(request.GetXid()) mac_request := request.GetChaddr() packet_response.SetChaddr(mac_request) var row1 sqlRow stmt, err := database.Prepare("SELECT * FROM IP_table WHERE MAC = ?") if err != nil { log.Fatal(err) } err1 := stmt.QueryRow(mac_request.String()).Scan(&row1.Id, &row1.IP, &row1.MAC, &row1.Release_date) if err1 != nil { fmt.Println("Erreur lors de la requête 1") fmt.Println(err1) } stmt, err = database.Prepare("SELECT * FROM IP_table WHERE MAC = ?") if err != nil { log.Fatal(err) } var row2 sqlRow err2 := stmt.QueryRow("").Scan(&row2.Id, &row2.IP, &row2.MAC, &row2.Release_date) if err2 != nil { fmt.Println("Erreur lors de la requête 2") fmt.Println(err2) } stmt, err = database.Prepare("SELECT * FROM IP_table WHERE ( CURRENT_TIMESTAMP > release_date )") if err != nil { log.Fatal(err) } var row3 sqlRow err3 := stmt.QueryRow().Scan(&row3.Id, &row3.IP, &row3.MAC, &row3.Release_date) if err3 != nil { fmt.Println("Erreur lors de la requête 3") fmt.Println(err3) } // We allocate the IP for 3 minutes to give the time to receive a dhcp request if err1 == nil { packet_response.SetYiaddr(row1.IP) _, err = database.Exec( "UPDATE IP_table SET release_date=datetime(CURRENT_TIMESTAMP, '+3 minutes') WHERE id = ?", row1.Id) } else if err2 == nil { packet_response.SetYiaddr(row2.IP) _, err = database.Exec( "UPDATE IP_table SET release_date=datetime(CURRENT_TIMESTAMP, '+3 minutes'), MAC = ? WHERE id = ?", mac_request.String(), row2.Id) } else if err3 == nil { packet_response.SetYiaddr(row3.IP) _, err = database.Exec( "UPDATE IP_table SET release_date=datetime(CURRENT_TIMESTAMP, '+3 minutes'), MAC = ? WHERE id = ?", mac_request.String(), row3.Id) } else { fmt.Println("All IPs are used") packet_response.SetMessageType(6) packet_response.SetYiaddr("0.0.0.0") packet_response.SetSiaddr("0.0.0.0") } if err != nil { fmt.Println("Failed to check the database") log.Fatal(err) } packet_response.SetMessageType(2) packet_response.Options.Add(255, nil) // Sending the packet raddr := net.UDPAddr{IP: net.ParseIP("255.255.255.255"), Port: 68} laddr, err := net.ResolveUDPAddr("udp", parameters.IP_server+":"+strconv.Itoa(parameters.OutPort)) conn, err := net.DialUDP("udp", laddr, &raddr) if err != nil { fmt.Print(err) } n, err := conn.Write(packet_response.ToBytes()) if err != nil { fmt.Println(err) } if packet_response.GetMessageType() == 2 { fmt.Println("OFFER Sent - Bytes written : ", n) } else { fmt.Println("NACK Sent - Bytes written : ", n) } conn.Close() }
func ack(discover *dhcpPacket.DhcpPacket) { packet_response := dhcpPacket.NewDhcpPacket() // Fixed part in the body packet_response.SetOp(2) packet_response.SetCiaddr("0.0.0.0") packet_response.SetSiaddr(parameters.IP_server) packet_response.SetGiaddr("0.0.0.0") // Fixed part in the options packet_response.SetDhcpServer(parameters.IP_server) packet_response.SetLeaseTime(parameters.Allocation_time) packet_response.SetSubnetMask(parameters.Netmask) packet_response.SetDnsServer([]string{parameters.IP_DNS}) packet_response.SetRouter(parameters.IP_server) // Specific response to the client request packet_response.SetXid(discover.GetXid()) mac_request := discover.GetChaddr() packet_response.SetChaddr(mac_request) var row sqlRow stmt, err := database.Prepare("SELECT * FROM IP_table WHERE MAC = ?") if err != nil { fmt.Println(err) } err = stmt.QueryRow(mac_request.String()).Scan(&row.Id, &row.IP, &row.MAC, &row.Release_date) if err != nil { if err == sql.ErrNoRows { packet_response.SetMessageType(6) packet_response.SetYiaddr("0.0.0.0") packet_response.SetSiaddr("0.0.0.0") } else { fmt.Println("Failed to check the database") fmt.Println(err) } } else { // We allocate the IP for allocation_time packet_response.SetMessageType(5) packet_response.SetYiaddr(row.IP) timeModifier := "+" + strconv.Itoa(parameters.Allocation_time) + " seconds" _, err = database.Exec( "UPDATE IP_table SET release_date=datetime(CURRENT_TIMESTAMP, ?) WHERE id = ?", timeModifier, row.Id) if err != nil { fmt.Println(err) } } packet_response.Options.Add(255, nil) // Sending the packet destIp := "255.255.255.255" if discover.GetCiaddr().String() != "0.0.0.0" { destIp = discover.GetCiaddr().String() } raddr := net.UDPAddr{IP: net.ParseIP(destIp), Port: 68} laddr, err := net.ResolveUDPAddr("udp", parameters.IP_server+":"+strconv.Itoa(parameters.OutPort)) conn, err := net.DialUDP("udp", laddr, &raddr) if err != nil { fmt.Print(err) } n, err := conn.Write(packet_response.ToBytes()) if err != nil { fmt.Println(err) } if packet_response.GetMessageType() == 5 { fmt.Println("ACK Sent - Bytes written : ", n) } else { fmt.Println("NACK Sent - Bytes written : ", n) } conn.Close() }