83d290c5 |
1 | // SPDX-License-Identifier: GPL-2.0+ |
c25f01a6 |
2 | /* |
3 | * (C) Copyright 2016 |
4 | * Olliver Schinagl <oliver@schinagl.nl> |
c25f01a6 |
5 | */ |
6 | |
7 | #include <ctype.h> |
d2bf1152 |
8 | #include <stdbool.h> |
c25f01a6 |
9 | #include <stdint.h> |
10 | #include <stdio.h> |
11 | #include <stdlib.h> |
12 | #include <string.h> |
13 | #include <u-boot/crc.h> |
14 | |
15 | #define ARP_HLEN 6 /* Length of hardware address */ |
16 | #define ARP_HLEN_ASCII (ARP_HLEN * 2) + (ARP_HLEN - 1) /* with separators */ |
17 | #define ARP_HLEN_LAZY (ARP_HLEN * 2) /* separatorless hardware address length */ |
18 | |
19 | uint8_t nibble_to_hex(const char *nibble, bool lo) |
20 | { |
21 | return (strtol(nibble, NULL, 16) << (lo ? 0 : 4)) & (lo ? 0x0f : 0xf0); |
22 | } |
23 | |
24 | int process_mac(const char *mac_address) |
25 | { |
26 | uint8_t ethaddr[ARP_HLEN + 1] = { 0x00 }; |
27 | uint_fast8_t i = 0; |
28 | |
29 | while (*mac_address != '\0') { |
30 | char nibble[2] = { 0x00, '\n' }; /* for strtol */ |
31 | |
32 | nibble[0] = *mac_address++; |
33 | if (isxdigit(nibble[0])) { |
34 | if (isupper(nibble[0])) |
35 | nibble[0] = tolower(nibble[0]); |
36 | ethaddr[i >> 1] |= nibble_to_hex(nibble, (i % 2) != 0); |
37 | i++; |
38 | } |
39 | } |
40 | |
41 | for (i = 0; i < ARP_HLEN; i++) |
42 | printf("%.2x", ethaddr[i]); |
43 | printf("%.2x\n", crc8(0, ethaddr, ARP_HLEN)); |
44 | |
45 | return 0; |
46 | } |
47 | |
48 | void print_usage(char *cmdname) |
49 | { |
50 | printf("Usage: %s <mac_address>\n", cmdname); |
51 | puts("<mac_address> may be with or without separators."); |
52 | puts("Valid seperators are ':' and '-'."); |
53 | puts("<mac_address> digits are in base 16.\n"); |
54 | } |
55 | |
56 | int main(int argc, char *argv[]) |
57 | { |
58 | if (argc < 2) { |
59 | print_usage(argv[0]); |
60 | return 1; |
61 | } |
62 | |
63 | if (!((strlen(argv[1]) == ARP_HLEN_ASCII) || (strlen(argv[1]) == ARP_HLEN_LAZY))) { |
64 | puts("The MAC address is not valid.\n"); |
65 | print_usage(argv[0]); |
66 | return 1; |
67 | } |
68 | |
69 | if (process_mac(argv[1])) { |
70 | puts("Failed to calculate the MAC's checksum."); |
71 | return 1; |
72 | } |
73 | |
74 | return 0; |
75 | } |