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  }