// Tries to send a WOL to the given MAC. Returns true if one or more WOL packets were sent // or false if no subnet for the MAC is known or reachable. // NOTE: That this function returns true does not mean that the WOL has reached its target. func TriggerWake(macaddress string) bool { wake_target := []string{} if system := db.ServerWithMAC(macaddress); system != nil { wake_target = append(wake_target, strings.Split(system.Text("source"), ":")[0]) } if system := db.ClientWithMAC(macaddress); system != nil { wake_target = append(wake_target, strings.Split(system.Text("client"), ":")[0]) } if system := db.SystemFullyQualifiedNameForMAC(macaddress); system != "none" { wake_target = append(wake_target, system) } woken := false for i := range wake_target { if err := util.Wake(macaddress, wake_target[i]); err == nil { util.Log(1, "INFO! Sent Wake-On-LAN for MAC %v to %v", macaddress, wake_target[i]) woken = true // We do not break here, because the data in the serverDB or clientDB may // be stale and since we're sending UDP packets, there's no guarantee // that util.Wake() will fail even if the system is no longer there. // Since the WOL packets include the MAC address it can't hurt to // send more than necessary. } else { util.Log(0, "ERROR! Could not send Wake-On-LAN for MAC %v to %v: %v", macaddress, wake_target[i], err) } } return woken }
// Wakes up the machine with the MAC address job.Text("macaddress"). No other // elements from job are used. func Wake(job *xml.Hash) { macaddress := job.Text("macaddress") for i := 0; i < 10; i++ { woken := message.TriggerWake(macaddress) // While sending a few excess WOL packets should be harmless, spamming all // known networks with WOLs is very ugly, especially when it's completely // unnecessary. And if one of the above 3 WOL attempts succeeded, chances // are very good that we already hit our target. For that reason we only // perform network spamming if everything else has failed. if !woken { util.Log(0, "ERROR! Targetted Wake-On-LAN for MAC %v failed. Jericho protocol engaged!", macaddress) // We ask all known peers to join the fun. Let's raise hell and wake the dead! xmlmsg := xml.NewHash("xml", "header", "trigger_wake") xmlmsg.Add("source", "GOSA") xmlmsg.Add("macaddress", macaddress) xmlmsg.Add("trigger_wake") //empty element because gosa-si does it like that for _, server := range db.ServerAddresses() { xmlmsg.FirstOrAdd("target").SetText(server) message.Peer(server).Ask(xmlmsg.String(), "") } // Now spam all networks with our WOL packet. for _, network := range db.SystemNetworksKnown() { util.Log(1, "INFO! Spamming network %v with Wake-On-LAN for MAC %v", network, macaddress) if err := util.Wake(macaddress, network); err != nil { util.Log(0, "ERROR! Could not send Wake-On-LAN for MAC %v to %v: %v", macaddress, network, err) } } } for k := 0; k < 3; k++ { time.Sleep(time.Duration(10+rand.Intn(5)) * time.Second) if message.GosaPing(macaddress) { util.Log(1, "INFO! Wake-On-LAN for MAC %v successful. Client is awake.", macaddress) goto confirmed_awake } } } util.Log(0, "ERROR! Giving up Wake-On-LAN for MAC %v", macaddress) confirmed_awake: }