All pastes #444560 Raw Edit

Untitled

public c v1 · immutable
·published 2007-04-17 12:01 UTC
rendered paste body
/*  * * $Id: main.c,v 1.65 2005/10/07 02:30:30 psionic Exp $ */#include <sys/types.h>#include <sys/time.h>#include "../config.h"#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <string.h>#ifdef __FreeBSD__#include <netinet/in_systm.h>#endif#include <netdb.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netinet/in.h>#include <netinet/ip.h>#ifdef HAVE_NET_ETHERNET_H#include <net/ethernet.h>#define MACTYPE u_char#define ETHERCONV(ether) (ether)#endif#ifdef HAVE_NETINET_IF_ETHER_H#include <net/if.h>#include <netinet/if_ether.h>#ifndef MACTYPE#define MACTYPE uchar_t#endif#ifndef ETHERCONV#define ETHERCONV(ether) (&((ether).ether_addr_octet))#endif#endif#include <pthread.h>#include <pcap.h>#include <libnet.h>#include "ugly.h"static int BIGSERVER;#ifndef ETHER_ADDR_LEN#define ETHER_ADDR_LEN 6#endif#include "log.h"#include "hash.h"#define SERVER_PORT 3434#define HASHSIZE 512/* xbox broadcasts to FF:FF:FF:FF:FF:FF */static const char broadcastmac[ETHER_ADDR_LEN] = { 	0xFF, 0xFF, 0xFF, 	0xFF, 0xFF, 0xFF};/* multicast mac address is 01:00:5E:XX:XX:XX */static const char multicastmac[ETHER_ADDR_LEN] = {	0x01, 0x00, 0x5E,	0x00, 0x00, 0x00, /* Last 3 octets are unknown and don't matter */};struct proxy;typedef struct xbox {	MACTYPE macaddr[ETHER_ADDR_LEN];	struct proxy *proxy; /* The IP address of the proxy this xbox is located at */	time_t lastseen; /* Last time a packet was seen from this xbox */} xbox_t;static hash_t *xboxen = NULL;/* Container for remote proxies */typedef struct proxy {	int ip; /* The ip address of this proxy */	struct in_addr addr;	int port; /* The port! */	int fd; /* File descriptor for the connection to this proxy */	hash_t *xboxen; /* Table containing known xboxes on this proxy */} proxy_t;static hash_t *proxies = NULL;static fd_set proxysocks;static char *progname;static char *pcapdev = NULL;static char *bindhost = NULL;static struct in_addr bindaddr;static char *proxyserver = NULL;/* Some defaults */static int use_udp = 1;static int forwardmulticast = 0;static int forwardbroadcast = 0;static int forwardxbox = 1;static int serverport = SERVER_PORT;static char *user_filter = NULL;my_libnet_t *libnet;void addxbox(MACTYPE *macaddr, proxy_t *ppt);proxy_t *addproxy(struct sockaddr_in *addr, int sock);void packet_handler(u_char *args, const struct pcap_pkthdr *head,					  const u_char *packet);void remove_proxy(proxy_t *ppt);void connect_to_proxy();int recv_from_proxy(proxy_t *ppt);void distribute_packet(proxy_t *ppt, char *packet, int pktlen);void usage() {	debuglog(0, "Usage: %s [-bxm] [-u] [-B <bind ip>] [-s <server>] [-i <dev>] [-d <debuglevel>] [-p <port>] [-h]",				progname);	debuglog(0, "-x              forward xbox system link packets");	debuglog(0, "-b              forward broadcast traffic");	debuglog(0, "-m              forward multicast packets");	debuglog(0, "-u              use udp encapsulation instead of tcp (default)");	debuglog(0, "-B <bind_ip>    specify a specific ip to bind the listen server to");	debuglog(0, "-s <server>     specify another proxy to send packets to");	debuglog(0, "-i <dev>        ethernet device to sniff packets on");	debuglog(0, "-d <level>      specify debug level, (0-1000)");	debuglog(0, "-p <port>       which port to send data on when talkin to other proxies");	debuglog(0, "-f <bpf filter> an additional bpf filter string you wish to use");	debuglog(0, "-h              this message!");}int comparemac(const void *k1, const void *k2) {	extern loglevel;	if (loglevel >= 30) {		char foo[25];		strcpy(foo,ether_ntoa((struct ether_addr *)k1));		debuglog(30, "comparemac %s vs %s", foo, ether_ntoa((struct ether_addr *)k2));	}	return memcmp(k1, k2, ETHER_ADDR_LEN);}int compareip(const void *k1, const void *k2) {	int a, b;	a = *(unsigned int *)k1;	b = *(unsigned int *)k2;	debuglog(30, "compareip: %08x vs %08x = %d", a, b, (a < b ? -1 : (a > b ? 1 : 0)) );	return (a < b ? -1 : (a > b ? 1 : 0));}hash_val_t haship(const void *key) {	static unsigned long randbox[] = {		0x49848f1bU, 0xe6255dbaU, 0x36da5bdcU, 0x47bf94e9U,		0x8cbcce22U, 0x559fc06aU, 0xd268f536U, 0xe10af79aU,		0xc1af4d69U, 0x1d2917b5U, 0xec4c304dU, 0x9ee5016cU,		0x69232f74U, 0xfead7bb3U, 0xe9089ab6U, 0xf012f6aeU,	};	const unsigned char *str = key;	int c = 0;	hash_val_t acc = 0;	while (c < sizeof(int)) {		acc ^= randbox[(*str + acc) & 0xf];		acc = (acc << 1) | (acc >> 31);		acc &= 0xffffffffU;		acc ^= randbox[((*str++ >> 4) + acc) & 0xf];		acc = (acc << 2) | (acc >> 30);		acc &= 0xffffffffU;		c++;	}	return acc;}hash_val_t hashmac(const void *key) {	static unsigned long randbox[] = {		0x49848f1bU, 0xe6255dbaU, 0x36da5bdcU, 0x47bf94e9U,		0x8cbcce22U, 0x559fc06aU, 0xd268f536U, 0xe10af79aU,		0xc1af4d69U, 0x1d2917b5U, 0xec4c304dU, 0x9ee5016cU,		0x69232f74U, 0xfead7bb3U, 0xe9089ab6U, 0xf012f6aeU,	};	const unsigned char *str = key;	int c = 0;	hash_val_t acc = 0;	while (c < ETHER_ADDR_LEN) {		acc ^= randbox[(*str + acc) & 0xf];		acc = (acc << 1) | (acc >> 31);		acc &= 0xffffffffU;		acc ^= randbox[((*str++ >> 4) + acc) & 0xf];		acc = (acc << 2) | (acc >> 30);		acc &= 0xffffffffU;		c++;	}	return acc;}/*  * Packet handling routine. */void packet_handler(u_char *args, const struct pcap_pkthdr *head,						  const u_char *packet) {	struct ether_header *eptr;	eptr = (struct ether_header *) packet;	/* Try adding this xbox to the list */	//debuglog(1, "Adding xbox in packet_handler");	addxbox((MACTYPE *) ETHERCONV(eptr->ether_shost), 0);	/* If this packet is sent to our local net, ignore it... */	if (hash_lookup(xboxen, ETHERCONV(eptr->ether_shost)) != NULL) {		debuglog(15, "Packet!");		debuglog(3, "From: %s", ether_ntoa((struct ether_addr *)ETHERCONV(eptr->ether_shost)));		debuglog(3, "To: %s", ether_ntoa((struct ether_addr *)ETHERCONV(eptr->ether_dhost)));	}	/*	 * If this is broadcast or multicast, send it to all known proxies	 */	if ((memcmp(ETHERCONV(eptr->ether_dhost), broadcastmac, ETHER_ADDR_LEN) == 0) ||		 (forwardmulticast && (memcmp(ETHERCONV(eptr->ether_dhost), multicastmac, 3) == 0))) {		hscan_t hs;		hnode_t *node;		debuglog(11, "BROADCAST");		hash_scan_begin(&hs, proxies);		while ((node = hash_scan_next(&hs))) {			proxy_t *p = (proxy_t *)(node->hash_data);			/* Make sure the source addr of this packet is not getting			 * sent this packet. Do not send! */			if ((hash_lookup(p->xboxen, ETHERCONV(eptr->ether_shost)) != NULL))				continue;			debuglog(3, "Sending ethernet packet to %s:%d [Length: %d]", inet_ntoa(p->addr), htons(p->port), head->caplen);			if (use_udp) {				struct sockaddr_in to;				to.sin_addr = p->addr;				//to.sin_port = htons(serverport);				to.sin_port = p->port;				to.sin_family = PF_INET;				sendto(p->fd, packet, head->caplen, 0, (struct sockaddr *)&to, sizeof(struct sockaddr));			} else {				/* TCP */			}		}	} else {		/* This packet is for a specific mac */		proxy_t *p;		hnode_t *box;		box = hash_lookup(xboxen, ETHERCONV(eptr->ether_dhost));		if (box == NULL) {			debuglog(3, "Unknown destination %s, hasn't been seen yet.", 						ether_ntoa((struct ether_addr *)ETHERCONV(eptr->ether_dhost)));			return;		}		debuglog(3, "Found packet destined for %s! (len: %d)", 					ether_ntoa((struct ether_addr *)ETHERCONV(eptr->ether_dhost)),					head->caplen);		p = ((xbox_t *)(box->hash_data))->proxy;		if (p == NULL) {			debuglog(3, "Packet is destined for this net, ignore it");			return;		}		debuglog(3, "Proxy is: %s", (p == NULL ? "Local" : inet_ntoa(p->addr)));		if (use_udp) {			struct sockaddr_in to;			to.sin_addr = p->addr;			//to.sin_port = htons(serverport);			to.sin_port = p->port;			to.sin_family = PF_INET;			sendto(p->fd, packet, head->caplen, 0, (struct sockaddr *)&to, sizeof(struct sockaddr));		} else {			/* TCP */		}	}}proxy_t *addproxy(struct sockaddr_in *addr, int sock) {	proxy_t *newproxy = NULL;	hnode_t *proxy = NULL;	debuglog(5, "Data from proxy: %s", inet_ntoa(addr->sin_addr));	proxy = hash_lookup(proxies, &(addr->sin_addr.s_addr));	if (proxy == NULL) {		hscan_t hs;		hnode_t *node;		newproxy = malloc(sizeof(proxy_t));		newproxy->ip = (int) addr->sin_addr.s_addr;		newproxy->addr = addr->sin_addr;		newproxy->port = addr->sin_port;		/* XXX: Is this correct?		 * If we're using UDP, 'sock' is the server udp socket, so this is correct		 * If we're using TCP, well... tcp doesn't work properly yet.  */		newproxy->fd = sock;		newproxy->xboxen = hash_create(HASHSIZE, comparemac, hashmac);		debuglog(1, "NEW PROXY FOUND: %s", inet_ntoa(addr->sin_addr));		hash_alloc_insert(proxies, &(newproxy->ip), newproxy);		/* Check known proxy connections for data */		hash_scan_begin(&hs, proxies);		fprintf(stderr, "KNOWN PROXIES:\n");		while ((node = hash_scan_next(&hs))) {			proxy_t *p = (proxy_t *)(node->hash_data);			struct sockaddr_in i;			i.sin_addr.s_addr = *(int *)(node->hash_key);			fprintf(stderr, "PROXY: %s\n", inet_ntoa(p->addr));		}		fprintf(stderr, "END\n");		return newproxy;	} else {		proxy_t *p = proxy->hash_data;		debuglog(15, "Packet from known proxy...");		if (p->port != addr->sin_port) {			debuglog(0, "Port changed on client %s (%d -> %d)", inet_ntoa(addr->sin_addr), 						p->port, addr->sin_port);			p->port = addr->sin_port;		}		return (proxy->hash_data);	}}void addxbox(MACTYPE *macaddr, proxy_t *ppt) {	xbox_t *newbox = NULL;	hnode_t *box = NULL;	box = hash_lookup(xboxen, macaddr);	if (box == NULL) {		hscan_t hs;		hnode_t *node;		//fprintf(stderr, "NEW XBOX FOUND: %s / LOCATION: %s\n", 		//ether_ntoa((struct ether_addr *)macaddr),		//(ppt == NULL ? "Local" : inet_ntoa(ppt->addr)));		debuglog(1, "NEW XBOX FOUND: %s", ether_ntoa((struct ether_addr *)macaddr));		debuglog(1, "\tLocation: %s", (ppt == NULL ? "Local" : inet_ntoa(ppt->addr)));		newbox = malloc(sizeof(xbox_t));		memcpy(newbox->macaddr,macaddr,ETHER_ADDR_LEN);		//fprintf(stderr, "Stored macaddr: %s\n\n", ether_ntoa((struct ether_addr *)(newbox->macaddr)));		newbox->lastseen = time(NULL);		newbox->proxy = ppt;		//hash_alloc_insert(xboxen, macaddr, newbox);		hash_alloc_insert(xboxen, newbox->macaddr, newbox);		if (ppt != NULL) 			hash_alloc_insert(ppt->xboxen, newbox->macaddr, newbox);		/* Check known proxy connections for data */		hash_scan_begin(&hs, xboxen);		fprintf(stderr, "KNOWN XBOXES:\n");		while ((node = hash_scan_next(&hs))) {			xbox_t *x = (xbox_t *)(node->hash_data);			fprintf(stderr, "XBOX: %s\n", ether_ntoa((struct ether_addr *)x->macaddr));		}		fprintf(stderr, "END\n");	}}void pcap(void *args) {	pcap_t *handle;	struct bpf_program filter;	char errbuf[PCAP_ERRBUF_SIZE];	bpf_u_int32	mask, net;	char *bpf_filter;	char netstring[17];	char maskstring[17];	pcap_lookupnet(pcapdev, &net, &mask, errbuf);#define GETBYTE(data,i) (*(((unsigned char *)&data) + i))	sprintf(netstring, "%u.%u.%u.%u", GETBYTE(net, 0), GETBYTE(net,1),			  GETBYTE(net,2), GETBYTE(net, 3));	sprintf(maskstring, "%u.%u.%u.%u", GETBYTE(mask, 0), GETBYTE(mask,1),			  GETBYTE(mask,2), GETBYTE(mask, 3));	debuglog(0, "Network: %s / %s", netstring, maskstring);	/* A generous cap length */	handle = pcap_open_live(pcapdev, 2048, 1, 10, errbuf);	if (handle == NULL) {		debuglog(0, "Error trying to open %s: %s", pcapdev, errbuf);		//return 1;		pthread_exit(NULL);	}	libnet = my_libnet_init(pcapdev, errbuf);	if (libnet == NULL) {		debuglog(0, "libnet_init() failed: %s", errbuf);		pthread_exit(NULL);	}	debuglog(2, "Opened %s, listening for xbox traffic", pcapdev);	bpf_filter = malloc(1024);	memset(bpf_filter, 0, 1024);	if (user_filter != NULL) {		sprintf(bpf_filter, "(%s)", user_filter);		if (forwardmulticast || forwardbroadcast || forwardxbox)			sprintf(bpf_filter + strlen(bpf_filter), " and (");	}	/* Build the pcap bpf filter string */	if (forwardmulticast) {		sprintf(bpf_filter + strlen(bpf_filter), "(src net %s mask %s and (multicast))", netstring, maskstring);		if (forwardbroadcast || forwardxbox)			sprintf(bpf_filter + strlen(bpf_filter), " or ");	}	/* XXX: Should this match any broadcast? Ether broadcast? or just ip broadcast? */	if (forwardbroadcast) {		sprintf(bpf_filter + strlen(bpf_filter), "(ip broadcast)");		if (forwardxbox) 			sprintf(bpf_filter + strlen(bpf_filter), " or ");	}	if (forwardxbox)		sprintf(bpf_filter + strlen(bpf_filter), "(host 0.0.0.1)");	if (user_filter != NULL)		sprintf(bpf_filter + strlen(bpf_filter), ")");	debuglog(0, "pcap filter: %s", bpf_filter);	if (-1 == pcap_compile(handle, &filter, bpf_filter, 1, net)) {		debuglog(0, "%s: %s", progname, pcap_geterr(handle));		if (user_filter != NULL) {			debuglog(0, "%s: You specified an additional packet filter, it probably has an error", 						progname);			debuglog(0, "%s: The filter is '%s'", progname, user_filter);			debuglog(5, "%s: Generated filter: %s", progname, bpf_filter);		}		exit(-1);	}	pcap_setfilter(handle, &filter);	pcap_loop(handle, -1, packet_handler, NULL);	pcap_close(handle);	pthread_exit(NULL);}void proxy(void *args) {	int server;	struct sockaddr_in serveraddr;	FD_ZERO(&proxysocks);	if (use_udp) {		server = socket(PF_INET, SOCK_DGRAM, 0);	} else {		server = socket(PF_INET, SOCK_STREAM, 0);	}	BIGSERVER = server;	serveraddr.sin_family = PF_INET;	if (bindhost != NULL) {		serveraddr.sin_addr = bindaddr;	} else {		serveraddr.sin_addr.s_addr = INADDR_ANY;	}	serveraddr.sin_port = htons(serverport);	debuglog(5, "Binding to any on port %d", serverport);	if (bind(server, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr)) == -1) {		debuglog(0, "bind() failed: %s", strerror(errno));		pthread_exit(NULL);	}	if (!use_udp) {		if (listen(server, SOMAXCONN) < 0) {			debuglog(0, "listen() failed: %s", strerror(errno));			debuglog(0, "UDP: %d", use_udp);			pthread_exit(NULL);		}	}	debuglog(1, "Listening on port %d", serverport);	FD_SET(server, &proxysocks);	/* If server is non-null, connect to that server and listen for data on it */	if (proxyserver != NULL) {		connect_to_proxy();	}	for (;;) {		int fd;		struct sockaddr_in srcaddr;		int size = sizeof(struct sockaddr_in); /* sizeof(srcaddr) */		int sel;		struct timeval timeout;		struct fd_set proxycopy;		timeout.tv_sec = 10;		timeout.tv_usec = 0;		/* Some sort of select() thing here */		proxycopy = proxysocks;		FD_SET(server, &proxysocks);		debuglog(150, "select: %08x", proxysocks);		sel = select(FD_SETSIZE, &proxysocks, NULL, NULL, &timeout);		if (sel < 0) {			debuglog(0, "select() failed: %s", strerror(errno));			pthread_exit(NULL);		} else if (sel == 0) {			debuglog(150, "select() timed out waiting for data... trying again");			proxysocks = proxycopy;		} else {			hscan_t hs;			hnode_t *node;			debuglog(15, "Data ready from %d descriptors", sel);			if (use_udp) {				if (FD_ISSET(server, &proxysocks)) {					proxy_t p;					p.fd = server;					debuglog(13, "Data received on udp");					if (recv_from_proxy(&p) > 0 )						FD_SET(server, &proxysocks);					else						FD_CLR(server, &proxysocks);				} else {					FD_SET(server, &proxysocks);				}			} else { /* if using TCP... */			} 		} /* else, selected data is available */	} /* infinite loop */}void connect_to_proxy() {	int sock;	struct sockaddr_in destaddr;	struct hostent *hostdata;	struct in_addr in;	//proxy_t *newproxy;	if (use_udp) {		if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {			debuglog(0, "socket() failed: %s", strerror(errno));			pthread_exit(NULL);		}	} else {		if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {			debuglog(0, "socket() failed: %s", strerror(errno));			pthread_exit(NULL);		}	}	/* XXX: Should we bind the socket here to port 3434? */	if ((hostdata = gethostbyname(proxyserver))== NULL) {		debuglog(0, "gethostbyname() failed: %s", strerror(errno));		pthread_exit(NULL);	}	/* Grab the IP this hostname is, this is an ugly oneliner */	memcpy(&(in.s_addr),hostdata->h_addr_list[0],hostdata->h_length);	debuglog(1, "%s is %s (%s)", proxyserver, hostdata->h_name, inet_ntoa(in));	//inet_ntoa((struct in_addr *)(hostdata->h_addr_list[0])));	destaddr.sin_family = PF_INET;	destaddr.sin_addr = in;	destaddr.sin_port = htons(serverport);	if (use_udp) {		debuglog(30, "Sending UDP hello packet to %s", proxyserver);		if (sendto(BIGSERVER, NULL, 0, 0, (struct sockaddr *)&destaddr, sizeof(struct sockaddr)) < 0) {			debuglog(0, "sendto() failed [while saying hi]: %s", strerror(errno));			pthread_exit(NULL);		}	} else { /* TCP */	} 	/* After we establish a connection with the proxy server host,	 * we should completely forget about this relationship 	 * (us being the client). Now, add it to the list of	 * known proxies and move along.	 */	addproxy(&destaddr, BIGSERVER);	FD_SET(sock, &proxysocks);}int recv_from_proxy(proxy_t *ppt) {	int bytes = 0;	int pktlen = 0;	int total;	char *packet;	if (use_udp) {		bytes = 4;		pktlen = 8192;	} else {		bytes = recv(ppt->fd, &pktlen, 4, 0);		debuglog(100, "Bytes read: [%d] %d", bytes, pktlen);		/* if bytes read is 0, then the connection was closed. */		if (bytes < 0) {			debuglog(0, "recv_from_proxy - recv() (1) failed: %s", strerror(errno));			return bytes;		} else if (bytes == 0) {			remove_proxy(ppt);			return 0;		}	}	packet = malloc(pktlen);	if (use_udp) {		struct sockaddr_in from;		int len = sizeof(struct sockaddr);		bytes = recvfrom(ppt->fd, packet, pktlen, 0, (struct sockaddr *)&from, &len);		pktlen = bytes; /* XXX: Is this a good idea? */		ppt = addproxy(&from, ppt->fd);	} else {		bytes = recv(ppt->fd, packet, pktlen, 0);	}	if (bytes < 0) {		if (use_udp)			debuglog(0, "recv_from_proxy - recvfrom() (2) failed: %s", strerror(errno));		else			debuglog(0, "recv_from_proxy - recv() (2) failed: %s", strerror(errno));		return bytes;	} if (bytes == 0) {		if (!use_udp) 			remove_proxy(ppt);		return 0;	}	//debuglog(1, "Adding xbox in  recv_from_proxy");	addxbox(ETHERCONV(((struct ether_header *)packet)->ether_shost), ppt);	debuglog(1, "Packet received from %s. Length: %d vs %d (%s)", 				inet_ntoa(ppt->addr), bytes, pktlen,				(bytes == pktlen ? "OK" : "FRAGMENTED"));	if (bytes < pktlen) {		total = bytes;		while (total < pktlen) {			bytes = recv(ppt->fd, packet + total, pktlen - total, 0);			debuglog(1, "REASSEMBLY PROGRESS - %s. Length: %d vs %d", inet_ntoa(ppt->addr), total, pktlen);			total += bytes;		}	}	distribute_packet(ppt, packet, bytes);	free(packet);	return bytes;}void distribute_packet(proxy_t *ppt, char *packet, int pktlen) {	struct ether_header *eptr;	u_short ether_type;	int bytes = 0;	eptr = (struct ether_header *)packet;	ether_type = ntohs(eptr->ether_type);	debuglog(30, "----- REMOTE PACKET From: %s", 				ether_ntoa((struct ether_addr *)ETHERCONV(eptr->ether_shost)));	debuglog(30, "----- REMOTE PACKET To: %s",				ether_ntoa((struct ether_addr *)ETHERCONV(eptr->ether_dhost)));	bytes = my_libnet_write_link_layer(libnet,pcapdev,packet,pktlen);	if (bytes < 0) {		debuglog(0, "FATAL ERROR WRITING RAW PACKET TO DEVICE");	} else {		debuglog(4, "Packet dumped on local net (%s), bytes vs length = %d vs %d", 					pcapdev, bytes, pktlen);	}	if (get_log_level() > 10)		hexdump(packet, pktlen);}void remove_proxy(proxy_t *ppt) {	hscan_t hs;	hnode_t *node;	debuglog(1, "Removing proxy %s", inet_ntoa(ppt->addr));	hash_scan_begin(&hs, proxies);	while ((node = hash_scan_next(&hs))) {		proxy_t *p = (proxy_t *)(node->hash_data);		if (ppt->ip == p->ip) {			hash_delete(proxies, node);			break;		}	}}int main(int argc, char **argv) {	char errbuf[PCAP_ERRBUF_SIZE];	//int *pthread_return;	char ch;	pthread_t pcapthread, proxythread;	progname = argv[0];	/* Initialization and Defaults */	xboxen = hash_create(HASHSIZE, comparemac, hashmac);	proxies = hash_create(HASHSIZE, compareip, haship);	set_log_level(0);	/* Argument Processing */	while ((ch = getopt(argc, argv, "B:bxmus:i:d:h?p:f:")) != -1) {		switch (ch) {			case 'B':				bindhost = malloc(strlen(optarg) + 1);				//strlcpy(bindhost,optarg,strlen(optarg) + 1);				strcpy(bindhost,optarg);				if (inet_aton(bindhost, &bindaddr) == 0) {					bindhost = NULL;					debuglog(0, "-B flag: Invalid IP address '%s'", bindhost);				}			case 'b':				debuglog(10, "-b flag, enabling broadcast forwarding");				forwardbroadcast = 1;				break;			case 'd':				set_log_level(atoi(optarg));				break;			case 'f':				user_filter = malloc(strlen(optarg));				strcpy(user_filter, optarg);				break;			case 'i':				pcapdev = malloc(strlen(optarg) + 1);				memset(pcapdev,0,strlen(optarg) + 1);				//strlcpy(pcapdev,optarg,strlen(optarg) + 1);				strncpy(pcapdev,optarg,strlen(optarg));				debuglog(10, "-i flag, setting device to %s", pcapdev);				break;			case 'm':				debuglog(10, "-m flag, enabling multicast forwarding");				forwardmulticast = 1;				break;			case 'p':				serverport = atoi(optarg);				debuglog(10, "-p flag, setting proxy port to %d", serverport);				break;			case 's':				proxyserver = malloc(strlen(optarg) + 1);				memset(proxyserver,0,strlen(optarg) + 1);				//strlcpy(proxyserver,optarg,strlen(optarg) + 1);				strncpy(proxyserver,optarg,strlen(optarg));				debuglog(10, "-s flag, setting proxy server to %s", proxyserver);				break;			case 'u':				debuglog(10, "-u flag, enabling udp");				use_udp = 1;				break;			case 'x':				debuglog(10, "-x flag, enabling xbox system link forwarding");				forwardxbox = 1;				break;			case 'h':			case '?':			default:				usage();				exit(1);				break;		}	}	argc -= optind;	argv += optind;	if (pcapdev == NULL) 		pcapdev = pcap_lookupdev(errbuf);	if (pcapdev == NULL) {		debuglog(0, "No device specified or unable to find a device to open.");		debuglog(0, "Error message: %s", errbuf);		return 1;	}	pthread_create(&pcapthread, NULL, (void*)pcap, NULL);	pthread_create(&proxythread, NULL, (void*)proxy, NULL);	pthread_join(pcapthread, NULL);	debuglog(0, "pcap thread exited unexpectedly");	exit(1);	pthread_join(proxythread, NULL);	return 0;}