github.com/iDigitalFlame/xmt@v0.5.4/device/network.go (about) 1 // Copyright (C) 2020 - 2023 iDigitalFlame 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with this program. If not, see <https://www.gnu.org/licenses/>. 15 // 16 17 package device 18 19 import ( 20 "net" 21 22 "github.com/iDigitalFlame/xmt/data" 23 "github.com/iDigitalFlame/xmt/util" 24 ) 25 26 type device struct { 27 Name string 28 Address []Address 29 Mac hardware 30 } 31 type hardware uint64 32 33 // Network is a basic listing of network interfaces. Used to store and refresh 34 // interface lists. 35 type Network []device 36 37 // Len returns the number of detected interfaces detected. 38 func (n Network) Len() int { 39 return len(n) 40 } 41 func (h hardware) String() string { 42 var ( 43 b [17]byte 44 v int 45 ) 46 for n, i := uint8(0), uint8(0); i < 6; i++ { 47 if n = uint8(h >> ((5 - i) * 8)); i > 0 { 48 b[v] = ':' 49 v++ 50 } 51 b[v] = util.HexTable[n>>4] 52 b[v+1] = util.HexTable[n&0x0F] 53 v += 2 54 } 55 return string(b[:v]) 56 } 57 58 // Refresh collects the interfaces connected to this system and fills this 59 // Network object with the information. 60 // 61 // If previous Network information is contained in this Network object, it is 62 // cleared before filling. 63 func (n *Network) Refresh() error { 64 if len(*n) > 0 { 65 *n = (*n)[0:0] 66 } 67 l, err := net.Interfaces() 68 if err != nil { 69 return err 70 } 71 for i := range l { 72 if l[i].Flags&net.FlagUp == 0 || l[i].Flags&net.FlagLoopback != 0 || l[i].Flags&net.FlagPointToPoint != 0 { 73 continue 74 } 75 a, err := l[i].Addrs() 76 if err != nil || len(a) == 0 { 77 continue 78 } 79 c := device{Name: l[i].Name, Address: make([]Address, 0, len(a)), Mac: mac(l[i].HardwareAddr)} 80 for o := range a { 81 if o > 0xFF { 82 break 83 } 84 var t Address 85 switch z := a[o].(type) { 86 case *net.IPNet: 87 t.Set(z.IP) 88 case *net.IPAddr: 89 t.Set(z.IP) 90 default: 91 continue 92 } 93 if !t.IsGlobalUnicast() { 94 continue 95 } 96 c.Address = append(c.Address, t) 97 } 98 if len(c.Address) > 0 { 99 *n = append(*n, c) 100 } 101 } 102 return nil 103 } 104 func mac(h net.HardwareAddr) hardware { 105 _ = h[5] 106 return hardware( 107 uint64(h[0])<<40 | uint64(h[1])<<32 | uint64(h[2])<<24 | 108 uint64(h[3])<<16 | uint64(h[4])<<8 | uint64(h[5]), 109 ) 110 } 111 func (d device) MarshalStream(w data.Writer) error { 112 if err := w.WriteString(d.Name); err != nil { 113 return err 114 } 115 if err := d.Mac.MarshalStream(w); err != nil { 116 return err 117 } 118 l := uint8(len(d.Address)) 119 if err := w.WriteUint8(l); err != nil { 120 return err 121 } 122 for x := uint8(0); x < l; x++ { 123 if err := d.Address[x].MarshalStream(w); err != nil { 124 return err 125 } 126 } 127 return nil 128 } 129 130 // MarshalStream writes the data of this Network to the supplied Writer. 131 func (n Network) MarshalStream(w data.Writer) error { 132 l := uint8(len(n)) 133 if err := w.WriteUint8(l); err != nil { 134 return err 135 } 136 for x := uint8(0); x < l; x++ { 137 if err := n[x].MarshalStream(w); err != nil { 138 return err 139 } 140 } 141 return nil 142 } 143 func (h hardware) MarshalStream(w data.Writer) error { 144 return w.WriteUint64(uint64(h)) 145 } 146 func (d *device) UnmarshalStream(r data.Reader) error { 147 if err := r.ReadString(&d.Name); err != nil { 148 return err 149 } 150 if err := d.Mac.UnmarshalStream(r); err != nil { 151 return err 152 } 153 l, err := r.Uint8() 154 if err != nil { 155 return err 156 } 157 d.Address = make([]Address, l) 158 for x := uint8(0); x < l; x++ { 159 if err := d.Address[x].UnmarshalStream(r); err != nil { 160 return err 161 } 162 } 163 return nil 164 } 165 166 // UnmarshalStream reads the data of this Network from the supplied Reader. 167 func (n *Network) UnmarshalStream(r data.Reader) error { 168 l, err := r.Uint8() 169 if err != nil { 170 return err 171 } 172 *n = make(Network, l) 173 for x := uint8(0); x < l; x++ { 174 if err := (*n)[x].UnmarshalStream(r); err != nil { 175 return err 176 } 177 } 178 return nil 179 } 180 func (h *hardware) UnmarshalStream(r data.Reader) error { 181 return r.ReadUint64((*uint64)(h)) 182 }