/*
steps:
* main() @mac.c
* read_mac_all()
* handle_mac_all(MAP_READ, mac_array)
* scan_mtd_info(scriptname) // check /proc/yyy for word "xxxxx" and return the device name(scriptname) under /dev
* map_file(scriptname, MAP_READ, &ptr, &len, &ifd)
fstat(ifd, &sbuf)
ptr = mmap(0, sbuf.st_size, prot, MAP_SHARED, ifd, 0) // map file ifd(scriptname) to memory
* for each line in script file
* do operation
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <mtd-api.h>
#define MAP_READ 1
#define MAP_RDWR 2
#undef MAC_DEBUG
//#define MAC_DEBUG
#ifdef MAC_DEBUG
#define mac_debug(x...) fprintf(stderr,x)
#else
#define mac_debug(x...)
#endif
static int
map_file(char *filename, int opcode, char **pptr, int *plen, int *pfd)
{
int ifd = -1;
char *ptr;
int flags;
off_t offset;
flags = (opcode == MAP_READ) ? O_RDONLY : O_RDWR;
ifd = open(filename, flags);
if (ifd < 0) {
mac_debug("Can't open %s: %s/n", filename, strerror(errno));
return MAC_ERROR_SYS;
}
/*returns mtd->size */
offset = lseek(ifd, 0, SEEK_END);
if (offset < 0) {
mac_debug("Can't lseek %s: %s/n", filename, strerror(errno));
close(ifd);
return MAC_ERROR_SYS;
}
ptr = malloc(offset);
if (ptr == NULL) {
mac_debug("Can't alloc memory,%s/n", strerror(errno));
close(ifd);
return MAC_ERROR_SYS;
}
if (lseek(ifd, 0, SEEK_SET) == -1) {
mac_debug("Can't alloc memory,%s/n", strerror(errno));
close(ifd);
return MAC_ERROR_SYS;
}
if (read(ifd, ptr, offset) != offset) {
mac_debug("Can't read %s: %s/n", filename, strerror(errno));
close(ifd);
return MAC_ERROR_SYS;
}
*pptr = ptr;
*plen = offset;
*pfd = ifd;
return MAC_ERROR_OK;
}
static int
unmap_file(int opcode, char *ptr, int len, int ifd)
{
int ret = MAC_ERROR_OK;
if (opcode == MAP_RDWR) {
struct erase_info_user erase;
erase.start = 0;
erase.length = len;
if (lseek(ifd, 0, SEEK_SET) == -1) {
ret = MAC_ERROR_SYS;
mac_debug("Can't seek the MTD device./n");
goto done;
}
/* erase the blocks to write */
if (ioctl(ifd, MEMERASE, &erase) < 0) {
ret = MAC_ERROR_SYS;
mac_debug("Can't erase the MTD device./n");
goto done;
}
if (write(ifd, ptr, len) != len) {
ret = MAC_ERROR_SYS;
mac_debug(" Can't write %s/n", strerror(errno));
goto done;
}
}
done:
return ret;
}
static void
close_file(char *ptr, int ifd)
{
free(ptr);
close(ifd);
}
static int
readline_from_buffer(char *s, int n, char *ptr, int *pos, int total)
{
register char *cs;
memset(s, 0, n);
cs = s;
while ((--n > 0) && (*pos < total)) {
if ((*cs++ = *(ptr + (*pos)++)) == '/n')
break;
}
*cs = '/0';
return (*pos >= total && cs == s) ? 0 : 1;
}
static int
scan_mtd_info(char *filename)
{
FILE *fp;
char line[256];
int i;
int ret = MAC_ERROR_MTD_FILE;
if ((fp = fopen("/proc/yyy", "r+")) == NULL) {
return MAC_ERROR_SYS;
}
while (fgets(line, sizeof (line), fp) != NULL) {
if (strstr(line, "xxxxxx") != NULL) {
sscanf(line, "mtd%d: ", &i);
sprintf(filename, "/dev/mtd%d", i);
ret = MAC_ERROR_OK;
break;
}
}
fclose(fp);
return ret;
}
static int
handle_mac_by_ifindex(int opcode, unsigned int ifindex, unsigned char mac_buf[])
{
char line[256];
unsigned int mac[6];
char *ptr;
int pos;
int len;
int ifd = -1;
char *start;
int unit;
int oldlen, newlen;
char scriptname[32];
int ret;
if (ifindex >= TSMAC_MAX_ETH_UNITS)
return MAC_ERROR_ILLEGAL;
if ((ret = scan_mtd_info(scriptname)) != MAC_ERROR_OK) {
return ret;
}
if ((ret = map_file(scriptname, opcode, &ptr, &len, &ifd)) != MAC_ERROR_OK) {
return ret;
}
pos = 0;
start = ptr;
ret = MAC_ERROR_NOT_FOUND;
while (readline_from_buffer(line, sizeof (line), ptr, &pos, len)) {
if (sscanf(line, " set ethaddr%d %02x:%02x:%02x:%02x:%02x:%02x",
&unit, &mac[0], &mac[1], &mac[2], &mac[3],
&mac[4], &mac[5]) == 7) {
if (unit == ifindex) {
switch (opcode) {
case MAP_RDWR:
oldlen = strlen(line);
memset(line, ' ', oldlen);
sprintf(line,
"set ethaddr%d %02x:%02x:%02x:%02x:%02x:%02x",
unit, mac_buf[0], mac_buf[1], mac_buf[2],
mac_buf[3], mac_buf[4], mac_buf[5]);
newlen = strlen(line);
/*remove ending /n' */
*(line + newlen) = ' ';
/*add ending /n' */
*(line + oldlen - 1) = '/n';
memcpy(start, line, oldlen);
ret = MAC_ERROR_OK;
break;
case MAP_READ:
/*implicit type conversion */
mac_buf[0] = mac[0];
mac_buf[1] = mac[1];
mac_buf[2] = mac[2];
mac_buf[3] = mac[3];
mac_buf[4] = mac[4];
mac_buf[5] = mac[5];
ret = MAC_ERROR_OK;
break;
}
}
}
start = ptr + pos;
}
if ((opcode == MAP_RDWR) && (ret == MAC_ERROR_OK))
ret = unmap_file(opcode, ptr, len, ifd);
close_file(ptr, ifd);
return ret;
}
static int
handle_mac_all(int opcode, unsigned char mac_array[][6])
{
char line[256];
char scriptname[32];
unsigned int mac[6];
char *ptr;
int pos;
int len;
int ifd = -1;
char *start;
int unit;
int oldlen, newlen;
int ret;
int result[TSMAC_MAX_ETH_UNITS];
if ((ret = scan_mtd_info(scriptname)) != MAC_ERROR_OK) {
return ret;
}
if ((ret = map_file(scriptname, opcode, &ptr, &len, &ifd)) != MAC_ERROR_OK) {
return ret;
}
pos = 0;
start = ptr;
for (unit = 0; unit < TSMAC_MAX_ETH_UNITS; ++unit) {
result[unit] = 0;
}
while (readline_from_buffer(line, sizeof (line), ptr, &pos, len)) {
if (sscanf(line, " set ethaddr%d %02x:%02x:%02x:%02x:%02x:%02x",
&unit, &mac[0], &mac[1], &mac[2], &mac[3],
&mac[4], &mac[5]) == 7) {
if (unit < TSMAC_MAX_ETH_UNITS) {
switch (opcode) {
case MAP_RDWR:
oldlen = strlen(line);
memset(line, ' ', oldlen);
sprintf(line,
"set ethaddr%d %02x:%02x:%02x:%02x:%02x:%02x",
unit, mac_array[unit][0], mac_array[unit][1],
mac_array[unit][2], mac_array[unit][3],
mac_array[unit][4], mac_array[unit][5]);
newlen = strlen(line);
*(line + newlen) = ' ';
*(line + oldlen - 1) = '/n';
memcpy(start, line, oldlen);
result[unit] = 1;
break;
case MAP_READ:
/*implicit type conversion */
mac_array[unit][0] = mac[0];
mac_array[unit][1] = mac[1];
mac_array[unit][2] = mac[2];
mac_array[unit][3] = mac[3];
mac_array[unit][4] = mac[4];
mac_array[unit][5] = mac[5];
result[unit] = 1;
break;
}
}
}
start = ptr + pos;
}
ret = MAC_ERROR_OK;
for (unit = 0; unit < TSMAC_MAX_ETH_UNITS; ++unit) {
if (result[unit] != 1) {
ret = MAC_ERROR_NOT_FOUND;
break;
}
}
if ((opcode == MAP_RDWR) && (ret == MAC_ERROR_OK))
ret = unmap_file(opcode, ptr, len, ifd);
close_file(ptr, ifd);
return ret;
}
/*
INPUT:
ifindex(in) - index of interface.
mac (out) - mac address buffer. 6 byte unsigned char array.
Return:
0 - ok
<0 - error code
*/
int
read_mac_by_ifindex(unsigned int ifindex, unsigned char mac[])
{
return handle_mac_by_ifindex(MAP_READ, ifindex, mac);
}
/*
INPUT:
ifindex(in) - index of interface.
mac (in) - mac address buffer. 6 byte unsigned char array.
Return:
0 - ok
<0 - error code
*/
int
write_mac_by_ifindex(unsigned int ifindex, unsigned char mac[])
{
return handle_mac_by_ifindex(MAP_RDWR, ifindex, mac);
}
/*
INPUT:
mac_array (in) - mac address array.
Return:
0 - ok
<0 - error code
*/
int
write_mac_all(unsigned char mac_array[][6])
{
return handle_mac_all(MAP_RDWR, mac_array);
}
/*
INPUT:
mac_array (out) - mac address array.
Return:
0 - ok
<0 - error code
*/
int
read_mac_all(unsigned char mac_array[][6])
{
return handle_mac_all(MAP_READ, mac_array);
}
#undef TEST
#define TEST
#ifdef TEST
static void
print_mac(unsigned char *mac)
{
printf("%02x:%02x:%02x:%02x:%02x:%02x/n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
int
main()
{
//read/write all
{
int i;
unsigned char mac[TSMAC_MAX_ETH_UNITS][6];
unsigned char new_mac[TSMAC_MAX_ETH_UNITS][6] = {
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
{0x00, 0x02, 0x02, 0x03, 0x04, 0x05},
{0x00, 0x03, 0x02, 0x03, 0x04, 0x05}
};
if (read_mac_all(mac)) {
printf("read all error/n");
return -1;
}
printf("read all/n");
for (i = 0; i < TSMAC_MAX_ETH_UNITS; ++i) {
print_mac(mac[i]);
}
if (write_mac_all(new_mac)) {
printf("write all error/n");
return -1;
}
if (read_mac_all(mac)) {
printf("write all error/n");
return -1;
}
printf("after write all/n");
for (i = 0; i < TSMAC_MAX_ETH_UNITS; ++i) {
print_mac(mac[i]);
}
}
// read/write by index
{
unsigned char mac[6];
unsigned char new_mac[6] = { 0x00, 0x05, 0x05, 0x05, 0x05, 0x06 };
printf("read by index/n");
if (read_mac_by_ifindex(2, mac)) {
printf(" read_mac_by_ifindex error/n");
return -1;
}
print_mac(mac);
if (write_mac_by_ifindex(2, new_mac)) {
printf(" write_mac_by_ifindex error/n");
return -1;
}
printf("after by index/n");
if (read_mac_by_ifindex(2, mac)) {
printf(" read_mac_by_ifindex error/n");
return -1;
}
print_mac(mac);
}
return 0;
}
#endif