e1e12cd96f27292a772a1a8b2e62323efb81689b
[openwrt/openwrt.git] / package / maccalc / src / main.c
1 /*
2 * MAC address manupulation utility
3 *
4 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
9 *
10 */
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <stdint.h>
15 #include <string.h>
16 #include <unistd.h>
17
18 #define MAC_ADDRESS_LEN 6
19
20 #define ERR_INVALID 1
21 #define ERR_IO 2
22
23 static void usage(void);
24
25 char *maccalc_name;
26
27 static int parse_mac(const char *mac_str, unsigned char *buf)
28 {
29 int t;
30
31 t = sscanf(mac_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
32 &buf[0], &buf[1], &buf[2], &buf[3], &buf[4], &buf[5]);
33
34 if (t != MAC_ADDRESS_LEN)
35 return ERR_INVALID;
36
37 return 0;
38 }
39
40 static void print_mac(unsigned char *buf)
41 {
42 printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
43 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
44 }
45
46 static int maccalc_do_add(int argc, const char *argv[])
47 {
48 unsigned char mac[MAC_ADDRESS_LEN];
49 uint32_t t;
50 int err;
51 int i;
52
53 if (argc != 2) {
54 usage();
55 return ERR_INVALID;
56 }
57
58 err = parse_mac(argv[0], mac);
59 if (err)
60 return err;
61
62 i = atoi(argv[1]);
63
64 t = (mac[3] << 16) | (mac[4] << 8) | mac[5];
65 t += i;
66 mac[3] = (t >> 16) & 0xff;
67 mac[4] = (t >> 8) & 0xff;
68 mac[5] = t & 0xff;
69
70 print_mac(mac);
71 return 0;
72 }
73
74 static int maccalc_do_logical(int argc, const char *argv[],
75 unsigned char (*op)(unsigned char n1,
76 unsigned char n2))
77 {
78 unsigned char mac1[MAC_ADDRESS_LEN];
79 unsigned char mac2[MAC_ADDRESS_LEN];
80 int err;
81 int i;
82
83 if (argc != 2) {
84 usage();
85 return ERR_INVALID;
86 }
87
88 err = parse_mac(argv[0], mac1);
89 if (err)
90 return err;
91
92 err = parse_mac(argv[1], mac2);
93 if (err)
94 return err;
95
96 for (i = 0; i < MAC_ADDRESS_LEN; i++)
97 mac1[i] = op(mac1[i],mac2[i]);
98
99 print_mac(mac1);
100 return 0;
101 }
102
103 static int maccalc_do_mac2bin(int argc, const char *argv[])
104 {
105 unsigned char mac[MAC_ADDRESS_LEN];
106 ssize_t c;
107 int err;
108
109 if (argc != 1) {
110 usage();
111 return ERR_INVALID;
112 }
113
114 err = parse_mac(argv[0], mac);
115 if (err)
116 return err;
117
118 c = write(STDOUT_FILENO, mac, sizeof(mac));
119 if (c != sizeof(mac)) {
120 fprintf(stderr, "failed to write to stdout\n");
121 return ERR_IO;
122 }
123
124 return 0;
125 }
126
127 static int maccalc_do_bin2mac(int argc, const char *argv[])
128 {
129 unsigned char mac[MAC_ADDRESS_LEN];
130 ssize_t c;
131
132 if (argc != 0) {
133 usage();
134 return ERR_INVALID;
135 }
136
137 c = read(STDIN_FILENO, mac, sizeof(mac));
138 if (c != sizeof(mac)) {
139 fprintf(stderr, "failed to read from stdin\n");
140 return ERR_IO;
141 }
142
143 print_mac(mac);
144 return 0;
145 }
146
147 static unsigned char op_or(unsigned char n1, unsigned char n2)
148 {
149 return n1 | n2;
150 }
151
152 static int maccalc_do_or(int argc, const char *argv[])
153 {
154 return maccalc_do_logical(argc, argv, op_or);
155 }
156
157 static unsigned char op_and(unsigned char n1, unsigned char n2)
158 {
159 return n1 & n2;
160 }
161
162 static int maccalc_do_and(int argc, const char *argv[])
163 {
164 return maccalc_do_logical(argc, argv, op_and);
165 }
166
167 static unsigned char op_xor(unsigned char n1, unsigned char n2)
168 {
169 return n1 ^ n2;
170 }
171
172 static int maccalc_do_xor(int argc, const char *argv[])
173 {
174 return maccalc_do_logical(argc, argv, op_xor);
175 }
176
177 static void usage(void)
178 {
179 fprintf(stderr,
180 "Usage: %s <command>\n"
181 "valid commands:\n"
182 " add <mac> <number>\n"
183 " and|or|xor <mac1> <mac2>\n"
184 " mac2bin <mac>\n"
185 " bin2mac\n",
186 maccalc_name);
187 }
188
189 int main(int argc, const char *argv[])
190 {
191 int (*op)(int argc, const char *argv[]);
192 int ret;
193
194 maccalc_name = (char *) argv[0];
195
196 if (argc < 2) {
197 usage();
198 return EXIT_FAILURE;
199 }
200
201 if (strcmp(argv[1], "add") == 0) {
202 op = maccalc_do_add;
203 } else if (strcmp(argv[1], "and") == 0) {
204 op = maccalc_do_and;
205 } else if (strcmp(argv[1], "or") == 0) {
206 op = maccalc_do_or;
207 } else if (strcmp(argv[1], "xor") == 0) {
208 op = maccalc_do_xor;
209 } else if (strcmp(argv[1], "mac2bin") == 0) {
210 op = maccalc_do_mac2bin;
211 } else if (strcmp(argv[1], "bin2mac") == 0) {
212 op = maccalc_do_bin2mac;
213 } else {
214 fprintf(stderr, "unknown command '%s'\n", argv[1]);
215 usage();
216 return EXIT_FAILURE;
217 }
218
219 argc -= 2;
220 argv += 2;
221
222 ret = op(argc, argv);
223 if (ret)
224 return EXIT_FAILURE;
225
226 return EXIT_SUCCESS;
227 }