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

Reply via email to