pla_util_2.1.2_815e4700/common/src/mac_addresses.adb

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
--  SPDX-License-Identifier: GPL-3.0-or-later
------------------------------------------------------------------------
--  pla-util - A power line adapter utility
--  Copyright (C) 2016-2023 John Serock
--
--  This file is part of pla-util.
--
--  pla-util is free software: you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation, either version 3 of the License, or
--  (at your option) any later version.
--
--  pla-util is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--  GNU General Public License for more details.
--
--  You should have received a copy of the GNU General Public License
--  along with this program. If not, see <http://www.gnu.org/licenses/>.
------------------------------------------------------------------------
with Ada.Characters.Handling;
with GNAT.Formatted_String;

use GNAT.Formatted_String;

package body MAC_Addresses is

   function "<" (Left  : MAC_Address_Type;
                 Right : MAC_Address_Type) return Boolean is

      use type Octets.Octet_Type;

   begin

      for I in MAC_Address_Octets_Type'Range loop

         if Left.Octets (I) /= Right.Octets (I) then
            return Left.Octets (I) < Right.Octets (I);
         end if;

      end loop;

      return False;

   end "<";

   function Create_MAC_Address (MAC_Address_Octets : MAC_Address_Octets_Type) return MAC_Address_Type is

      MAC_Address : MAC_Address_Type;

   begin

      MAC_Address.Octets := MAC_Address_Octets;

      return MAC_Address;

   end Create_MAC_Address;

   function Get_Octets (Self : MAC_Address_Type) return MAC_Address_Octets_Type is

   begin

      return Self.Octets;

   end Get_Octets;

   function Image (Self : MAC_Address_Type) return MAC_Address_Image_Type is

      Hex_Format : Formatted_String := +"%02x%c%02x%c%02x%c%02x%c%02x%c%02x";
      S          : MAC_Address_Image_Type;

   begin

      for I in Self.Octets'First .. Self.Octets'Last - 1 loop
         Hex_Format := Octets.Octet_Format (Format => Hex_Format,
                                            Var    => Self.Octets (I)) & ':';
      end loop;

      Hex_Format := Octets.Octet_Format (Format => Hex_Format,
                                         Var    => Self.Octets (Self.Octets'Last));

      S := -Hex_Format;

      return S;

   end Image;

   function Is_Unicast (Self : MAC_Address_Type) return Boolean is

      use type Octets.Octet_Type;

   begin

      return (Self.Octets (1) and 1) = 0;

   end Is_Unicast;

   function Value (MAC_Address_Image : MAC_Address_Image_Type) return MAC_Address_Type is

      Separator : constant Character := ':';

   begin

      if MAC_Address_Image (3) /= Separator or else MAC_Address_Image (6) /= Separator or else MAC_Address_Image (9) /= Separator or else
        MAC_Address_Image (12) /= Separator or else MAC_Address_Image (15) /= Separator
      then

         raise MAC_Address_Error with "Invalid MAC Address format " & MAC_Address_Image;

      end if;

      if MAC_Address_Image = "00:00:00:00:00:00" then
         return Null_MAC_Address;
      end if;

      declare

         Lower_Image        : constant MAC_Address_Image_Type := Ada.Characters.Handling.To_Lower (Item => MAC_Address_Image);
         MAC_Address_Octets : MAC_Address_Octets_Type;

      begin

         if Lower_Image = "ff:ff:ff:ff:ff:ff" then
            return Broadcast_MAC_Address;
         end if;

         MAC_Address_Octets (1) := Octets.Octet_Type'Value ("16#" & Lower_Image (1 .. 2) & '#');
         MAC_Address_Octets (2) := Octets.Octet_Type'Value ("16#" & Lower_Image (4 .. 5) & '#');
         MAC_Address_Octets (3) := Octets.Octet_Type'Value ("16#" & Lower_Image (7 .. 8) & '#');
         MAC_Address_Octets (4) := Octets.Octet_Type'Value ("16#" & Lower_Image (10 .. 11) & '#');
         MAC_Address_Octets (5) := Octets.Octet_Type'Value ("16#" & Lower_Image (13 .. 14) & '#');
         MAC_Address_Octets (6) := Octets.Octet_Type'Value ("16#" & Lower_Image (16 .. 17) & '#');

         return Create_MAC_Address (MAC_Address_Octets => MAC_Address_Octets);

      exception

         when Constraint_Error =>

            raise MAC_Address_Error with "Invalid MAC Address " & MAC_Address_Image;

      end;

   end Value;

end MAC_Addresses;