Attached is a patch which adds a few enhancements to the network support
in RPCemu. The changes are:
- Add support for bridged networking - if bridgename is set in the
config file instead of ipaddress then the interface will be joined
to the specified bridge. This allows it to be bridged with the
hosts ethernet interface and avoids the need for iptables rules to
be used to NAT the traffic.
- Make sure host and guest have a consistent view of the MAC address
for the emulated ethernet card - the existing code had the host
using 01:02:03:04:05:06 and the guest using 00:00:00:00:00:00 which
caused problems with bridge networking. Now the host calculates an
address (or uses one from the config file) and allows the guest to
get hold of it via an extra SWI call.
- Block SIGIO until the handler is setup, or we may get a signal
before we're ready which causes rpcemu to crash as the default
action for SIGIO is to terminate the process.
Hope this helps,
Tom
--
Tom Hughes ([email protected])
http://www.compton.nu/
Index: src/rpcemu.c
===================================================================
--- src/rpcemu.c (revision 145)
+++ src/rpcemu.c (working copy)
@@ -39,6 +39,8 @@
int timetolive = 0;
const char *username = NULL;
const char *ipaddress = NULL;
+const char *macaddress = NULL;
+const char *bridgename = NULL;
void loadconfig();
void saveconfig();
@@ -188,6 +190,8 @@
mousehackon=get_config_int(NULL,"mouse_following",1);
username=get_config_string(NULL,"username",NULL);
ipaddress=get_config_string(NULL,"ipaddress",NULL);
+ macaddress=get_config_string(NULL,"macaddress",NULL);
+ bridgename=get_config_string(NULL,"bridgename",NULL);
}
void saveconfig()
Index: src/rpcemu.h
===================================================================
--- src/rpcemu.h (revision 145)
+++ src/rpcemu.h (working copy)
@@ -111,6 +111,8 @@
extern int stretchmode;
extern const char *username;
extern const char *ipaddress;
+extern const char *macaddress;
+extern const char *bridgename;
extern uint32_t soundaddr[4];
Index: src/network-linux.c
===================================================================
--- src/network-linux.c (revision 145)
+++ src/network-linux.c (working copy)
@@ -17,6 +17,7 @@
#include <pwd.h>
#include <grp.h>
#include <signal.h>
+#include <linux/sockios.h>
#include "rpcemu.h"
#include "mem.h"
@@ -28,6 +29,9 @@
/* Max packet is 1500 bytes plus headers */
static unsigned char buffer[1522];
+/* Hardware address */
+static unsigned char hwaddr[6];
+
static podule *poduleinfo = NULL;
/* Structures to represent the RISC OS view of things */
@@ -91,8 +95,8 @@
int fd;
int sd;
- if (ipaddress == NULL) {
- printf("IP address not configured\n");
+ if (ipaddress == NULL && bridgename == NULL) {
+ printf("IP address/bridge name not configured\n");
return -1;
}
@@ -116,14 +120,30 @@
return -1;
}
- addr = (struct sockaddr_in *)(&(ifr.ifr_addr));
- addr->sin_family = AF_INET;
- addr->sin_port = 0;
- inet_aton(ipaddress, &(addr->sin_addr));
- if (ioctl(sd, SIOCSIFADDR, &ifr) == -1) {
- printf("Error assigning %s addr: %s\n",
- ifr.ifr_name, strerror(errno));
- return -1;
+ if (ipaddress) {
+ addr = (struct sockaddr_in *)(&(ifr.ifr_addr));
+ addr->sin_family = AF_INET;
+ addr->sin_port = 0;
+ inet_aton(ipaddress, &(addr->sin_addr));
+ if (ioctl(sd, SIOCSIFADDR, &ifr) == -1) {
+ printf("Error assigning %s addr: %s\n",
+ ifr.ifr_name, strerror(errno));
+ return -1;
+ }
+ } else if (bridgename) {
+ struct ifreq brifr;
+ if (ioctl(sd, SIOCGIFINDEX, &ifr) == -1) {
+ printf("Error interface index for %s: %s\n",
+ ifr.ifr_name, strerror(errno));
+ return -1;
+ }
+ strcpy(brifr.ifr_name, bridgename);
+ brifr.ifr_ifindex = ifr.ifr_ifindex;
+ if (ioctl(sd, SIOCBRADDIF, &brifr) == -1) {
+ printf("Error adding %s to bridge: %s\n",
+ ifr.ifr_name, strerror(errno));
+ return -1;
+ }
}
@@ -140,6 +160,27 @@
return -1;
}
+ if (macaddress) {
+ /* Parse supplied MAC address */
+ sscanf(macaddress, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+ &hwaddr[0], &hwaddr[1], &hwaddr[2],
+ &hwaddr[3], &hwaddr[4], &hwaddr[5]);
+ } else {
+ /* Get the hardware address */
+ if (ioctl(sd, SIOCGIFHWADDR, &ifr) == -1) {
+ printf("Error getting %s hardware address: %s\n", ifr.ifr_name,
strerror(errno));
+ return -1;
+ }
+
+ /* Calculate the emulated hardware address */
+ hwaddr[0] = 0x02;
+ hwaddr[1] = 0x00;
+ hwaddr[2] = 0xA4;
+ hwaddr[3] = ifr.ifr_hwaddr.sa_data[3];
+ hwaddr[4] = ifr.ifr_hwaddr.sa_data[4];
+ hwaddr[5] = ifr.ifr_hwaddr.sa_data[5];
+ }
+
close(sd);
if (fcntl(fd, F_SETFL, O_NONBLOCK | O_ASYNC) == -1) {
@@ -218,7 +259,7 @@
device and not a real ethernet then it doesn't need to
be unique, just different to the MAC on the other end
of the tunnel. */
- for (i=0;i<6;i++) buf[i] = i;
+ for (i=0;i<6;i++) buf[i] = hwaddr[i];
}
buf += 6;
@@ -340,6 +381,10 @@
rethinkpoduleints();
*retr0 = 0;
break;
+ case 4:
+ memcpyfromhost(r2, hwaddr, sizeof(hwaddr));
+ *retr0 = 0;
+ break;
default:
strcpyfromhost(r1, "Unknown RPCemu network SWI");
*retr0 = r1;
@@ -351,10 +396,16 @@
uid_t uid = 0;
gid_t gid = 0;
const char *user = username;
+ sigset_t oldmask;
+ sigset_t iomask;
/* Use configured username if available, otherwise see if
we are running from a sudo command */
if (user == NULL) user = getenv("SUDO_USER");
+ sigemptyset(&iomask);
+ sigaddset(&iomask, SIGIO);
+ sigprocmask(SIG_BLOCK, &iomask, &oldmask);
+
tunfd = tun_alloc();
if (tunfd == -1) printf("Networking unavailable\n");
@@ -376,5 +427,7 @@
poduleinfo = addpodule(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0);
if (poduleinfo == NULL) printf("No free podule for networking\n");
}
+
+ sigprocmask(SIG_SETMASK, &oldmask, NULL);
}
Index: riscos-progs/EtherRPCEm/intveneer.s
===================================================================
--- riscos-progs/EtherRPCEm/intveneer.s (revision 145)
+++ riscos-progs/EtherRPCEm/intveneer.s (working copy)
@@ -65,6 +65,17 @@
LDRNE a1, =errbuf
LDMFD sp!, {pc}
+ EXPORT |networkhwaddrswi|
+networkhwaddrswi
+ STMFD sp!,{lr}
+ MOV a3, a1
+ LDR a2, =errmess
+ MOV a1, #4
+ SWI &56ac4
+ TST a1, #0
+ LDRNE a1, =errbuf
+ LDMFD sp!, {pc}
+
EXPORT |callrx|
callrx
MOV r12, r3
Index: riscos-progs/EtherRPCEm/!System/310/Modules/Network/EtherRPCEm,ffa
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: riscos-progs/EtherRPCEm/Module.c
===================================================================
--- riscos-progs/EtherRPCEm/Module.c (revision 145)
+++ riscos-progs/EtherRPCEm/Module.c (working copy)
@@ -42,6 +42,7 @@
_kernel_oserror *networktxswi(struct mbuf *mbufs, int dest, int src, int
frametype);
_kernel_oserror *networkrxswi(struct mbuf *mbuf, rx_hdr *hdr, int *valid);
_kernel_oserror *networkirqswi(volatile int *irqstatus);
+_kernel_oserror *networkhwaddrswi(unsigned char *hwaddr);
void callrx(dib *dibaddr, struct mbuf *mbuf_chain, int claimaddr, int pwp);
// versionof DCI supported
@@ -219,6 +220,8 @@
return &ErrorNoBuff;
}
+ networkhwaddrswi((unsigned char *)work->dev_addr);
+
work->pwp=private_word;
// claim mbuf manager link
if(work->mbctl = calloc(1,sizeof(dci4_mbctl)),work->mbctl==NULL)
Index: riscos-progs/EtherRPCEm/cmhg/ModHdr
===================================================================
--- riscos-progs/EtherRPCEm/cmhg/ModHdr (revision 145)
+++ riscos-progs/EtherRPCEm/cmhg/ModHdr (working copy)
@@ -17,7 +17,7 @@
# file called LICENSE.
#
-help-string: EtherRPCEm 1.00 © Alex Waugh and John Ballance/Castle
+help-string: EtherRPCEm 1.01 © Alex Waugh and John Ballance/Castle
title-string: EtherRPCEm
_______________________________________________
Rpcemu mailing list
[email protected]
http://www.riscos.info/cgi-bin/mailman/listinfo/rpcemu