Added tap support to etherslave tool.

This commit is contained in:
Dan Sumorok 2013-05-25 22:01:21 -04:00
parent c939be2d2d
commit 19b53082a3
3 changed files with 207 additions and 32 deletions

View File

@ -43,15 +43,27 @@
#include <Carbon/Carbon.h>
#define STR_MAX 256
#define MAX_ARGV 10
static int open_bpf(char *ifname);
static int open_tap(char *ifname);
static int retreive_auth_info(void);
static int main_loop(int sd);
static int main_loop(int sd, int use_bpf);
static int run_cmd(const char *cmd);
static void handler(int signum);
static int install_signal_handlers();
static void do_exit();
static int removeBridge = 0;
int main(int argc, char **argv)
{
char *if_name;
int ret;
int ret = 255;
int sd;
int tapNum;
int use_bpf;
if (argc != 2) {
return 255;
@ -59,32 +71,41 @@ int main(int argc, char **argv)
if_name = argv[1];
do {
ret = retreive_auth_info();
if (ret != 0) {
return 254;
ret = 254;
break;
}
fflush(stdout);
if(sscanf(if_name, "tap%d", &tapNum) == 1) {
sd = open_tap(if_name);
use_bpf = 0;
} else {
sd = open_bpf(if_name);
use_bpf = 0;
}
if (sd < 0) {
return 253;
ret = 253;
break;
}
fflush(stdout);
ret = main_loop(sd);
if(install_signal_handlers() != 0) {
ret = 252;
break;
}
ret = main_loop(sd, use_bpf);
close(sd);
} while(0);
if (ret < 0) {
return 252;
}
do_exit();
return 0;
return ret;
}
static int main_loop(int sd)
static int main_loop(int sd, int use_bpf)
{
fd_set readSet;
char *outgoing, *incoming;
@ -98,10 +119,15 @@ static int main_loop(int sd)
int pkt_len;
int frame_len;
int pad;
char c = 0;
if(use_bpf) {
if (ioctl(sd, BIOCGBLEN, &blen) < 0) {
return -1;
}
} else {
blen = 2048;
}
incoming = malloc(blen);
if (incoming == NULL) {
@ -119,6 +145,9 @@ static int main_loop(int sd)
out_len = (unsigned short *)outgoing;
/* Let our parent know we are ready for business. */
write(0, &c, 1);
while (1) {
int i;
FD_ZERO(&readSet);
@ -164,7 +193,7 @@ static int main_loop(int sd)
}
if (FD_ISSET(sd, &readSet)) {
if (use_bpf && FD_ISSET(sd, &readSet)) {
int i;
ret = read(sd, incoming, blen);
@ -186,7 +215,11 @@ static int main_loop(int sd)
}
*in_len = pkt_len;
write(0, in_len, pkt_len + 2);
if(write(0, in_len, pkt_len + 2) < (pkt_len + 2)) {
fret = -10;
break;
}
if ((frame_len & 0x03) == 0) {
pad = 0;
} else {
@ -202,6 +235,24 @@ static int main_loop(int sd)
break;
}
}
if (!use_bpf && FD_ISSET(sd, &readSet)) {
in_len = (unsigned short *)incoming;
pkt_len = read(sd, incoming+2, blen-2);
if (pkt_len < 14) {
fret = -8;
break;
}
*in_len = ret;
if(write(0, in_len, pkt_len + 2) < (pkt_len + 2)) {
fret = -10;
break;
}
}
}
free(incoming);
@ -256,6 +307,44 @@ static int retreive_auth_info(void)
return 0;
}
static int open_tap(char *ifname)
{
char str[STR_MAX] = {0};
int sd;
snprintf(str, STR_MAX, "/dev/%s", ifname);
sd = open(str, O_RDWR);
if(sd < 0) {
return -1;
}
snprintf(str, STR_MAX, "/sbin/ifconfig %s up", ifname);
if(run_cmd(str) != 0) {
close(sd);
return -1;
}
snprintf(str, STR_MAX, "/sbin/ifconfig bridge0 create");
if(run_cmd(str) == 0) {
removeBridge = 1;
}
snprintf(str, STR_MAX, "/sbin/ifconfig bridge0 addm %s", ifname);
if(run_cmd(str) != 0) {
close(sd);
return -1;
}
snprintf(str, STR_MAX, "/sbin/ifconfig bridge0 up");
if(run_cmd(str) != 0) {
close(sd);
return -1;
}
return sd;
}
static int open_bpf(char *ifname)
{
u_int blen = 0;
@ -302,3 +391,83 @@ static int open_bpf(char *ifname)
return sd;
}
static int run_cmd(const char *cmd) {
char cmd_buffer[STR_MAX] = {0};
char *argv[MAX_ARGV + 1] = {0};
int i;
pid_t pid, waitpid;
int status = 0;
/* Collect arguments */
strncpy(cmd_buffer, cmd, STR_MAX-1);
argv[0] = strtok(cmd_buffer, " ");
for (i=1; i<MAX_ARGV; ++i) {
argv[i] = strtok(NULL, " ");
if (argv[i] == NULL) {
break;
}
}
/* Run sub process */
pid = fork();
if (pid == 0) {
/* Child process */
fclose(stdout);
fclose(stderr);
if (execve(argv[0], argv, NULL) < 0) {
perror("execve");
return -1;
}
} else {
/* Wait for child to exit */
waitpid = wait(&status);
if (waitpid < 0) {
perror("wait");
return -1;
}
if (status != 0) {
return -1;
}
}
return 0;
}
static void handler(int signum) {
do_exit();
exit(1);
}
static int install_signal_handlers() {
struct sigaction act = {0};
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
if(sigaction(SIGINT, &act, NULL) != 0) {
return -1;
}
if(sigaction(SIGHUP, &act, NULL) != 0) {
return -1;
}
if(sigaction(SIGTERM, &act, NULL) != 0) {
return -1;
}
return 0;
}
static void do_exit() {
if(removeBridge) {
run_cmd("/sbin/ifconfig bridge0 destroy");
}
}

View File

@ -57,6 +57,7 @@ FILE * run_tool(const char *if_name, const char *tool_name)
CFURLRef url_ref;
CFStringRef path_str;
CFStringRef tool_name_str;
char c;
bundle_ref = CFBundleGetMainBundle();
if(bundle_ref == NULL) {
@ -68,6 +69,7 @@ FILE * run_tool(const char *if_name, const char *tool_name)
url_ref = CFBundleCopyResourceURL(bundle_ref, tool_name_str,
NULL, NULL);
CFRelease(tool_name_str);
if(url_ref == NULL) {
return NULL;
@ -80,7 +82,6 @@ FILE * run_tool(const char *if_name, const char *tool_name)
return NULL;
}
CFIndex index = CFStringGetLength(path_str);
if(!CFStringGetCString(path_str, path_buffer, sizeof(path_buffer),
kCFStringEncodingUTF8)) {
CFRelease(path_str);
@ -126,5 +127,10 @@ FILE * run_tool(const char *if_name, const char *tool_name)
return NULL;
}
if(fread(&c, 1, 1, fp) != 1) {
fclose(fp);
return NULL;
}
return fp;
}

View File

@ -1161,16 +1161,16 @@ static bool open_ether_slave(const char *if_name)
FILE *fp;
char str[64];
if (get_mac_address(if_name, ether_addr) != 0) {
snprintf(str, sizeof(str), "Unable to find interface %s.",
if_name);
fp = run_tool(if_name, "etherslavetool");
if (fp == NULL) {
snprintf(str, sizeof(str), "Unable to run ether slave helper tool.");
WarningAlert(str);
return false;
}
fp = run_tool(if_name, "etherslavetool");
if (fp == NULL) {
snprintf(str, sizeof(str), "Unable to run ether slave helper tool.");
if (get_mac_address(if_name, ether_addr) != 0) {
snprintf(str, sizeof(str), "Unable to find interface %s.",
if_name);
WarningAlert(str);
return false;
}