github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/examples/fixmynetboot/main.go (about) 1 // Copyright 2017-2019 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "flag" 9 "fmt" 10 "log" 11 "net" 12 13 "github.com/mvdan/u-root-coreutils/pkg/checker" 14 ) 15 16 // fixmynetboot is a troubleshooting tool that can help you identify issues that 17 // won't let your system boot over the network. 18 // NOTE: this is a DEMO tool. It's here only to show you how to write your own 19 // checks and remediations. Don't use it in production. 20 21 var emergencyShellBanner = ` 22 ************************************************************************** 23 ** Interface checks failed, see the output above to debug the issue. * 24 ** Entering the emergency shell, where you can run "fixmynetboot" again, * 25 ** or any other LinuxBoot command. * 26 ************************************************************************** 27 ` 28 29 var doEmergencyShell = flag.Bool("shell", false, "Run emergency shell if checks fail") 30 31 func checkInterface(ifname string) error { 32 checklist := []checker.Check{ 33 { 34 Name: fmt.Sprintf("%s exists", ifname), 35 Run: checker.InterfaceExists(ifname), 36 Remediate: checker.InterfaceRemediate(ifname), 37 StopOnError: true, 38 }, 39 { 40 Name: fmt.Sprintf("%s link speed", ifname), 41 Run: checker.LinkSpeed(ifname, 400000), 42 Remediate: nil, 43 StopOnError: false, 44 }, 45 { 46 Name: fmt.Sprintf("%s link autoneg", ifname), 47 Run: checker.LinkAutoneg(ifname, true), 48 Remediate: nil, 49 StopOnError: false, 50 }, 51 { 52 Name: fmt.Sprintf("%s has link-local", ifname), 53 Run: checker.InterfaceHasLinkLocalAddress(ifname), 54 Remediate: nil, 55 StopOnError: true, 56 }, 57 { 58 Name: fmt.Sprintf("%s has global addresses", ifname), 59 Run: checker.InterfaceHasGlobalAddresses("eth0"), 60 Remediate: nil, 61 StopOnError: true, 62 }, 63 } 64 65 return checker.Run(checklist) 66 } 67 68 func getNonLoopbackInterfaces() ([]string, error) { 69 var interfaces []string 70 allInterfaces, err := net.Interfaces() 71 if err != nil { 72 return nil, err 73 } 74 for _, iface := range allInterfaces { 75 if iface.Flags&net.FlagLoopback == 0 { 76 interfaces = append(interfaces, iface.Name) 77 } 78 } 79 return interfaces, nil 80 } 81 82 func main() { 83 flag.Parse() 84 var ( 85 interfaces []string 86 err error 87 ) 88 ifname := flag.Arg(0) 89 if ifname == "" { 90 interfaces, err = getNonLoopbackInterfaces() 91 if err != nil { 92 log.Fatal(err) 93 } 94 } else { 95 interfaces = []string{ifname} 96 } 97 98 for _, ifname := range interfaces { 99 if err := checkInterface(ifname); err != nil { 100 if !*doEmergencyShell { 101 log.Fatal(err) 102 } 103 if err := checker.EmergencyShell(emergencyShellBanner)(); err != nil { 104 log.Fatal(err) 105 } 106 } 107 } 108 }