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