Discussion:
working example setup for source-based routing with ipfilter?
(too old to reply)
i***@netbsd.org
2011-07-13 15:04:35 UTC
Permalink
Hi,

I'm trying to setup my router for dual homing- as my "normal" ISP
grew IPv6 - but am not sure how I should do it.

interface pppoe1 receives packets for 2001:db8:1111::/48
interface pppoe2 receives packets for 2001:db8:2222::/48

The default route points to pppoe1.

The idea is to route outgoing packets to the interface that would
receive their source addresses (else my upstreams would filter them).

Would this work?:

block out on pppoe1 to pppoe2 from 2001:db8:2222::/48 to any

Regards,
-is

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Mouse
2011-07-13 15:28:58 UTC
Permalink
Post by i***@netbsd.org
The idea is to route outgoing packets to the interface that would
receive their source addresses (else my upstreams would filter them).
That kind of routing is exactly what srt interfaces are for. I just
now looked, and the version in the 5.1 source tarballs appears to at
least try to support INET6. NetBSD's version is missing a change that
makes it cooperate with "keep state" style firewalling (eg, most NAT
setups), but that is unlikely to matter for v6. However, it may be
effectively unmaintained; it doesn't seem to have real locking calls in
it, and might not work right on little-endian machines - comparing it
against my version I see an ntohl which I think I added when I started
using it on i386 (for most of its existence I was using it on sparc).

Still, might be worth trying.

Of course, if you have some reason for wanting to do this with ipfilter
in particular, then ignore me. :-)

/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML ***@rodents-montreal.org
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Matthias Scheler
2011-07-14 14:21:09 UTC
Permalink
Post by i***@netbsd.org
block out on pppoe1 to pppoe2 from 2001:db8:2222::/48 to any
That is not what I used in the past (more than five years ago).
If I remember correctly it looked something this:

pass out quick pppoe1 fastroute to pppoe2 from 2001:db8:2222::/48 to any

Kind regards
--
Matthias Scheler http://zhadum.org.uk/

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
i***@netbsd.org
2011-07-15 08:34:09 UTC
Permalink
Post by Mouse
Post by i***@netbsd.org
The idea is to route outgoing packets to the interface that would
receive their source addresses (else my upstreams would filter them).
That kind of routing is exactly what srt interfaces are for. I just
now looked, and the version in the 5.1 source tarballs appears to at
least try to support INET6.
Ah, I wasn't aware of that.
Post by Mouse
NetBSD's version is missing a change that
makes it cooperate with "keep state" style firewalling (eg, most NAT
setups), but that is unlikely to matter for v6. However, it may be
effectively unmaintained; it doesn't seem to have real locking calls in
it, and might not work right on little-endian machines - comparing it
against my version I see an ntohl which I think I added when I started
using it on i386 (for most of its existence I was using it on sparc).
Oh. Where is that ntohl ? Would you create a patch, please?
Post by Mouse
Still, might be worth trying.
Of course, if you have some reason for wanting to do this with ipfilter
in particular, then ignore me. :-)
hm... I'm needing it for production use...

-is

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Mouse
2011-07-15 14:44:47 UTC
Permalink
NetBSD's version is missing a change that makes it cooperate with
"keep state" style firewalling (eg, most NAT setups), but that is
unlikely to matter for v6. However, it may be effectively
unmaintained; it doesn't seem to have real locking calls in it, and
might not work right on little-endian machines - comparing it
against my version I see an ntohl which I think I added when I
started using it on i386 (for most of its existence I was using it
on sparc).
Oh. Where is that ntohl ? Would you create a patch, please?
Here are diffs between the if_srt.c in the 5.1 source tarballs and the
version I'm using on 4.0.1. (This seems a little backward, but looking
at the diffs I think this may be the more useful way.) These are the
full diffs, in case you want (eg) the locking changes I mentioned -
-current may have proper locking, but in case not this may help.

There are actually two ntohls, which you can find by searching for
ntohl in this patch; one is in the hunk beginning @@ -91,12 +98,20 @@,
the other, @@ -407,8 +574,16 @@.

The change that makes it play nice with NAT is the call to
pfil_run_hooks and the following code inside PFIL_HOOKS; the containing
hunk is large, so you might be better off searching for pfil_run_hooks.
(If you really want, the hunk begins @@ -152,193 +182,323 @@.)

Hm, the explicit copyright status comments seem to have got lost in my
version. I wonder how that happened. I'll add them back. Just to be
totally clear on the point: any copyright interest I may have in these
diffs I hereby release into the public domain.

/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML ***@rodents-montreal.org
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B

--- if_srt.c 2011-07-13 11:13:37.000000000 -0400
+++ /usr/src/sys/net/if_srt.c 2011-06-29 21:51:05.000000000 -0400
@@ -1,62 +1,69 @@
-/* $NetBSD: if_srt.c,v 1.8 2008/06/15 16:37:21 christos Exp $ */
-/* This file is in the public domain. */
-
-#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_srt.c,v 1.8 2008/06/15 16:37:21 christos Exp $");
-
#include "opt_inet.h"
+#include "opt_pfil_hooks.h"

#if !defined(INET) && !defined(INET6)
-#error "srt without INET/INET6?"
+#error "srt with neither INET nor INET6"
#endif

#ifndef SRT_MAXUNIT
#define SRT_MAXUNIT 255
#endif

-/* include-file bug workarounds */
-#include <sys/types.h> /* sys/conf.h */
-#include <sys/resource.h> /* sys/resourcevar.h (uvm/uvm_param.h, sys/mbuf.h) */
-#include <netinet/in.h> /* netinet/ip.h */
-#include <sys/param.h> /* sys/mbuf.h */
-#include <netinet/in_systm.h> /* netinet/ip.h */
-
-#include <sys/conf.h>
+#include <net/if.h>
+#include <net/bpf.h>
+#include <sys/lock.h>
#include <sys/mbuf.h>
+#include <sys/conf.h>
#include <sys/errno.h>
+#include <sys/event.h>
#include <sys/fcntl.h>
-#include <sys/param.h>
-#include <sys/ioctl.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/malloc.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <net/if_types.h>
+#include <machine/intr.h>
#include <machine/stdarg.h>

#include "if_srt.h"
#include "bpfilter.h"
+#include "opt_altq_enabled.h"

-/* until we know what to pass to bpfattach.... */
-#undef NBPFILTER
-#define NBPFILTER 0
+#ifdef PFIL_HOOKS
+/* XXX, but this is how ip_output.c does it... */
+extern struct pfil_head inet_pfil_hook;
+#endif

-typedef struct srt_rt RT;
typedef struct softc SOFTC;
+typedef struct srt_rt RT;

struct softc {
- struct ifnet intf; /* XXX interface botch */
+ struct ifnet intf;
+ struct simplelock lock;
int unit;
int nrt;
RT **rts;
- unsigned int flags; /* SSF_* values from if_srt.h */
+ unsigned int flags; /* SSF_* values from if_srt.h */
#define SSF_UCHG (SSF_MTULOCK) /* userland-changeable bits */
- unsigned int kflags; /* bits private to this file */
+ unsigned int kflags; /* internal */
#define SKF_CDEVOPEN 0x00000001
} ;

+/* Lock nesting:
+ softcv_lock
+ SOFTC locks
+ gblf_lock
+ That is, for example, never take softcv_lock when holding either a
+ SOFTC's lock or gblf_lock.
+ */
+static struct simplelock softcv_lock;
static SOFTC *softcv[SRT_MAXUNIT+1];
+static struct simplelock gblf_lock;
static unsigned int global_flags;

-/* Internal routines. */
+#define SRT_DEFMTU 1500
+#define SRT_MAXMTU 9000

static unsigned int ipv4_masks[33]
= { 0x00000000, /* /0 */
@@ -91,12 +98,20 @@
struct in_addr ia;
struct in6_addr ia6;
va_list ap;
+ unsigned int cmp4;

- ia.s_addr = 0; ia6.s6_addr[0] = 0; /* shut up incorrect -Wuninitialized */
+ /* gcc's -Wuninitialized thinks these may be used unitialized.
+ It's wrong, but how to explain that to it?
+ So we waste a few cycles. :( */
+ ia.s_addr = 0;
+ ia6.s6_addr[0] = 0;
+ cmp4 = 0;
+ /* End incorrect -Wuninitialized workaround */
va_start(ap,af);
switch (af)
{ case AF_INET:
ia = va_arg(ap,struct in_addr);
+ cmp4 = ntohl(ia.s_addr);
break;
case AF_INET6:
ia6 = va_arg(ap,struct in6_addr);
@@ -111,7 +126,7 @@
if (r->af != af) continue;
switch (af)
{ case AF_INET:
- if ((ia.s_addr & ipv4_masks[r->srcmask]) == r->srcmatch.v4.s_addr) return(r);
+ if ((cmp4 & ipv4_masks[r->srcmask]) == r->srcmatch.v4.s_addr) return(r);
break;
case AF_INET6:
if ((r->srcmask >= 8) && bcmp(&ia6,&r->srcmatch.v6,r->srcmask/8)) continue;
@@ -129,20 +144,35 @@
return(0);
}

-/* Network device interface. */
-
-static int srt_if_ioctl(struct ifnet *intf, u_long cmd, void *data)
+static int srt_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct ifaddr *ifa;
- int s;
+#define ifa ((struct ifaddr *)data)
+#define ifr ((struct ifreq *)data)
int err;
+ int s;
+ SOFTC *sc;

err = 0;
s = splnet();
+ sc = ifp->if_softc;
+ simple_lock(&sc->lock);
switch (cmd)
{ case SIOCSIFADDR:
+ switch (ifa->ifa_addr->sa_family)
+ {
+#ifdef INET
+ case AF_INET:
+#endif
+#ifdef INET6
+ case AF_INET6:
+#endif
+ break;
+ default:
+ err = EAFNOSUPPORT;
+ break;
+ }
+ break;
case SIOCSIFDSTADDR:
- ifa = (void *) data;
switch (ifa->ifa_addr->sa_family)
{
#ifdef INET
@@ -152,193 +182,323 @@
case AF_INET6:
#endif
break;
+/* XXX we should support INET6 too */
default:
err = EAFNOSUPPORT;
break;
}
- /* XXX do we need to do more here for either of these? */
break;
case SIOCSIFMTU:
+ if ((ifr->ifr_mtu < 576) || (ifr->ifr_mtu > SRT_MAXMTU))
+ { err = EINVAL;
+ break;
+ }
+ /* XXX should do tun-style INET6 MTU check */
+ ifp->if_mtu = ifr->ifr_mtu;
+ break;
case SIOCGIFMTU:
- if ((err = ifioctl_common(intf, cmd, data)) == ENETRESET)
- err = 0;
+ ifr->ifr_mtu = ifp->if_mtu;
+ break;
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ if (! ifr)
+ { err = EAFNOSUPPORT; /* XXX */
+ break;
+ }
+ switch (ifr->ifr_addr.sa_family)
+ {
+#ifdef INET
+ case AF_INET:
+#endif
+#ifdef INET6
+ case AF_INET6:
+#endif
+ break;
+ default:
+ err = EAFNOSUPPORT;
+ break;
+ }
+ break;
+ case SIOCSIFFLAGS:
break;
default:
err = EINVAL;
break;
}
+#undef ifa
+#undef ifr
+ simple_unlock(&sc->lock);
splx(s);
return(err);
}

static int srt_if_output(
- struct ifnet *intf,
+ struct ifnet *ifp,
struct mbuf *m,
- const struct sockaddr *to,
- struct rtentry *rtp )
+ struct sockaddr *dst,
+ struct rtentry *rt)
{
SOFTC *sc;
RT *r;
+ int rv;

- sc = intf->if_softc;
- if (! (intf->if_flags & IFF_UP))
+ sc = ifp->if_softc;
+ if (! (ifp->if_flags & IFF_UP))
{ m_freem(m);
return(ENETDOWN);
}
- switch (to->sa_family)
+ simple_lock(&sc->lock);
+ switch (dst->sa_family)
{
#ifdef INET
case AF_INET:
-#endif
{ struct ip *ip;
ip = mtod(m,struct ip *);
r = find_rt(sc,AF_INET,ip->ip_src);
}
break;
+#endif
#ifdef INET6
case AF_INET6:
-#endif
{ struct ip6_hdr *ip;
ip = mtod(m,struct ip6_hdr *);
r = find_rt(sc,AF_INET6,ip->ip6_src);
}
break;
+#endif
default:
- IF_DROP(&intf->if_snd);
+ simple_unlock(&sc->lock);
+ IF_DROP(&ifp->if_snd);
m_freem(m);
return(EAFNOSUPPORT);
break;
}
- /* XXX Do we need to bpf_tap? Or do higher layers now handle that? */
- /* if_gif.c seems to imply the latter. */
- intf->if_opackets ++;
+ ifp->if_opackets ++;
if (! r)
- { intf->if_oerrors ++;
+ { ifp->if_oerrors ++;
+ simple_unlock(&sc->lock);
m_freem(m);
return(0);
}
if (! (m->m_flags & M_PKTHDR))
- { printf("srt_if_output no PKTHDR\n");
+ { simple_unlock(&sc->lock);
+ printf("srt_if_output no PKTHDR\n");
m_freem(m);
return(0);
}
- intf->if_obytes += m->m_pkthdr.len;
+ ifp->if_obytes += m->m_pkthdr.len;
if (! (r->u.dstifp->if_flags & IFF_UP))
- { m_freem(m);
+ { simple_unlock(&sc->lock);
+ m_freem(m);
return(0); /* XXX ENETDOWN? */
}
- /* XXX is 0 the right last arg here? */
- return((*r->u.dstifp->if_output)(r->u.dstifp,m,&r->dst.sa,0));
+#ifdef PFIL_HOOKS
+ rv = pfil_run_hooks(&inet_pfil_hook,&m,r->u.dstifp,PFIL_OUT);
+ if (rv)
+ { simple_unlock(&sc->lock);
+ return(rv);
+ }
+ if (dst->sa_family == AF_INET)
+ { struct ip *ip;
+ ip = mtod(m,struct ip *);
+ ip->ip_sum = 0;
+ ip->ip_sum = in_cksum(m,ip->ip_hl<<2);
+ m->m_pkthdr.csum_flags &= ~M_CSUM_IPv4;
+ }
+#endif
+ /*
+ * We have to hold sc->lock across the underlying interface's output
+ * call, because it uses r->dst.sa. This means we will deadlock if
+ * someone configures a loop and then sends a packet to it - but
+ * that's not so bad; the alternative is to recurse until we run out
+ * of stack and panic.
+ */
+ /* XXX is 0 ok as the last arg here? */
+ rv = (*r->u.dstifp->if_output)(r->u.dstifp,m,&r->dst.sa,0);
+ simple_unlock(&sc->lock);
+ return(rv);
}

-static int srt_clone_create(struct if_clone *cl, int unit)
+#ifdef ALTQ
+/* I'm not sure how relevant ALTQ is in view of the way srt works... */
+static void srt_if_start(struct ifnet *ifp)
+{
+ printf("srt if_start called\n");
+}
+#endif
+
+static int srt_clone_create(struct if_clone *ifc, int unit)
{
SOFTC *sc;

if ((unit < 0) || (unit > SRT_MAXUNIT)) return(ENXIO);
+ simple_lock(&softcv_lock);
if (softcv[unit]) return(EBUSY);
- sc = malloc(sizeof(SOFTC),M_DEVBUF,M_WAIT);
- bzero(&sc->intf,sizeof(sc->intf)); /* XXX */
+ simple_unlock(&softcv_lock);
+ sc = malloc(sizeof(SOFTC),M_DEVBUF,M_WAITOK);
+ simple_lock(&softcv_lock);
+ if (softcv[unit])
+ { simple_unlock(&softcv_lock);
+ free(sc,M_DEVBUF);
+ return(EBUSY);
+ }
sc->unit = unit;
sc->nrt = 0;
sc->rts = 0;
sc->flags = 0;
sc->kflags = 0;
- if_initname(&sc->intf,cl->ifc_name,unit);
+ bzero(&sc->intf,sizeof(sc->intf)); /* XXX interface botch */
+ snprintf(&sc->intf.if_xname[0],sizeof(sc->intf.if_xname),"%s%d",ifc->ifc_name,sc->unit);
sc->intf.if_softc = sc;
sc->intf.if_mtu = 65535;
- sc->intf.if_flags = IFF_POINTOPOINT;
- sc->intf.if_type = IFT_OTHER;
sc->intf.if_ioctl = &srt_if_ioctl;
sc->intf.if_output = &srt_if_output;
- sc->intf.if_dlt = DLT_RAW;
+#ifdef ALTQ
+ sc->ifnet.if_start = &srt_if_start;
+#endif
+ sc->intf.if_flags = IFF_POINTOPOINT;
+ sc->intf.if_type = IFT_OTHER; /* XXX is IFT_OTHER right? */
+ { extern int ifqmaxlen; /* XXX belongs in a .h file */
+ sc->intf.if_snd.ifq_maxlen = ifqmaxlen;
+ }
+ sc->intf.if_collisions = 0;
+ sc->intf.if_ierrors = 0;
+ sc->intf.if_oerrors = 0;
+ sc->intf.if_ipackets = 0;
+ sc->intf.if_opackets = 0;
+ sc->intf.if_ibytes = 0;
+ sc->intf.if_obytes = 0;
+ sc->intf.if_dlt = DLT_NULL;
+ IFQ_SET_READY(&sc->intf.if_snd);
if_attach(&sc->intf);
if_alloc_sadl(&sc->intf);
-#if NBPFILTER > 0 /* see comment near top */
- bpfattach(&sc->intf,0/*???*/,0/*???*/);
+#if NBPFILTER > 0
+ bpfattach(&sc->intf,DLT_NULL,sizeof(u_int32_t));
#endif
+ simple_lock_init(&sc->lock);
softcv[unit] = sc;
+ simple_unlock(&softcv_lock);
return(0);
}

-static int srt_clone_destroy(struct ifnet *intf)
+static int srt_clone_destroy(struct ifnet *ifp)
{
SOFTC *sc;
+ int s;

- sc = intf->if_softc;
- if ((intf->if_flags & IFF_UP) || (sc->kflags & SKF_CDEVOPEN)) return(EBUSY);
-#if NBPFILTER > 0
- bpfdetach(intf);
-#endif
- if_detach(intf);
+ simple_lock(&softcv_lock);
+ sc = ifp->if_softc;
if ((sc->unit < 0) || (sc->unit > SRT_MAXUNIT))
{ panic("srt_clone_destroy: impossible unit %d\n",sc->unit);
}
- if (softcv[sc->unit] != sc)
+ if (sc != softcv[sc->unit])
{ panic("srt_clone_destroy: bad backpointer ([%d]=%p not %p)\n",
sc->unit,(void *)softcv[sc->unit],(void *)sc);
}
+ simple_lock(&sc->lock);
+ if ((ifp->if_flags & IFF_UP) || (sc->kflags & SKF_CDEVOPEN))
+ { simple_unlock(&sc->lock);
+ simple_unlock(&softcv_lock);
+ return(EBUSY);
+ }
softcv[sc->unit] = 0;
+ simple_unlock(&softcv_lock);
+ s = splnet();
+ IF_PURGE(&ifp->if_snd);
+ ifp->if_flags &= ~IFF_RUNNING;
+ splx(s);
+#if NBPFILTER > 0
+ bpfdetach(ifp);
+#endif
+ if_detach(ifp);
+ simple_unlock(&sc->lock);
free(sc,M_DEVBUF);
return(0);
}

-struct if_clone srt_clone =
- IF_CLONE_INITIALIZER("srt",&srt_clone_create,&srt_clone_destroy);
+struct if_clone srt_cloner
+ = IF_CLONE_INITIALIZER("srt",&srt_clone_create,&srt_clone_destroy);

-extern void srtattach(void);
-void srtattach(void)
+void srtattach(int);
+void srtattach(int n __attribute__((__unused__)))
{
int i;

for (i=SRT_MAXUNIT;i>=0;i--) softcv[i] = 0;
global_flags = 0;
- if_clone_attach(&srt_clone);
+ simple_lock_init(&softcv_lock);
+ simple_lock_init(&gblf_lock);
+ if_clone_attach(&srt_cloner);
}

-/* Special-device interface. */
+/* These are unnecessary for declaration; they are here to provoke errors
+ if the definitions below get out of sync with the macros. */
+static dev_type_open(srt_ctl_open);
+static dev_type_close(srt_ctl_close);
+static dev_type_read(srt_ctl_read);
+static dev_type_write(srt_ctl_write);
+static dev_type_ioctl(srt_ctl_ioctl);

-static int srt_open(dev_t dev, int flag, int mode, struct lwp *l)
+static int srt_ctl_open(dev_t dev, int flag, int mode, struct lwp *l)
{
- int unit;
SOFTC *sc;
+ int unit;

unit = minor(dev);
- if ((unit < 0) || (unit > SRT_MAXUNIT)) return(ENXIO);
+ simple_lock(&softcv_lock);
sc = softcv[unit];
- if (! sc) return(ENXIO);
+ if (! sc)
+ { simple_unlock(&softcv_lock);
+ return(ENXIO);
+ }
+ simple_lock(&sc->lock);
sc->kflags |= SKF_CDEVOPEN;
+ simple_unlock(&sc->lock);
+ simple_unlock(&softcv_lock);
return(0);
}

-static int srt_close(dev_t dev, int flag, int mode, struct lwp *l)
+static int srt_ctl_close(
+ dev_t dev __attribute__((__unused__)),
+ int flag __attribute__((__unused__)),
+ int mode __attribute__((__unused__)),
+ struct lwp *l __attribute__((__unused__)) )
{
int unit;
SOFTC *sc;

unit = minor(dev);
if ((unit < 0) || (unit > SRT_MAXUNIT)) return(ENXIO);
+ simple_lock(&softcv_lock);
sc = softcv[unit];
- if (! sc) return(ENXIO);
+ if (! sc)
+ { simple_unlock(&softcv_lock);
+ return(ENXIO);
+ }
+ simple_lock(&sc->lock);
sc->kflags &= ~SKF_CDEVOPEN;
+ simple_unlock(&sc->lock);
+ simple_unlock(&softcv_lock);
return(0);
}

-static int srt_ioctl(
- dev_t dev,
- u_long cmd,
- void *data,
- int flag,
- struct lwp *l )
+static int srt_ctl_read(dev_t dev __attribute__((__unused__)), struct uio *uio __attribute__((__unused__)), int flag __attribute__((__unused__)))
+{
+ return(EIO);
+}
+
+static int srt_ctl_write(dev_t dev __attribute__((__unused__)), struct uio *uio __attribute__((__unused__)), int flag __attribute__((__unused__)))
+{
+ return(EIO);
+}
+
+static int srt_ctl_ioctl_core(SOFTC *sc, u_long cmd, caddr_t data, int flag, struct lwp *l)
{
- SOFTC *sc;
RT *dr;
RT *scr;
- struct ifnet *intf;
+ struct ifnet *ifp;
char nbuf[IFNAMSIZ];

- sc = softcv[minor(dev)];
- if (! sc) panic("srt_ioctl: softc disappeared");
switch (cmd)
{ case SRT_GETNRT:
if (! (flag & FREAD)) return(EBADF);
@@ -353,6 +513,14 @@
dr->af = scr->af;
dr->srcmatch = scr->srcmatch;
dr->srcmask = scr->srcmask;
+ switch (scr->af)
+ {
+#ifdef INET
+ case AF_INET:
+ dr->srcmatch.v4.s_addr = htonl(scr->srcmatch.v4.s_addr);
+ break;
+#endif
+ }
strncpy(&dr->u.dstifn[0],&scr->u.dstifp->if_xname[0],IFNAMSIZ);
memcpy(&dr->dst,&scr->dst,scr->dst.sa.sa_len);
return(0);
@@ -378,17 +546,16 @@
if (dr->srcmask > 128) return(EIO);
break;
#endif
- break;
default:
return(EAFNOSUPPORT);
break;
}
- intf = ifunit(&nbuf[0]);
- if (intf == 0) return(ENXIO); /* needs translation */
+ ifp = ifunit(&nbuf[0]);
+ if (! ifp) return(ENXIO); /* needs translation */
if (dr->inx == sc->nrt)
{ RT **tmp;
tmp = malloc((sc->nrt+1)*sizeof(*tmp),M_DEVBUF,M_WAITOK);
- if (tmp == 0) return(ENOBUFS);
+ if (! tmp) return(ENOBUFS);
tmp[sc->nrt] = 0;
if (sc->nrt > 0)
{ memcpy(tmp,sc->rts,sc->nrt*sizeof(*tmp));
@@ -407,8 +574,16 @@
}
scr->af = dr->af;
scr->srcmatch = dr->srcmatch;
+ switch (scr->af)
+ {
+#ifdef INET
+ case AF_INET:
+ scr->srcmatch.v4.s_addr = ntohl(scr->srcmatch.v4.s_addr);
+ break;
+#endif
+ }
scr->srcmask = dr->srcmask;
- scr->u.dstifp = intf;
+ scr->u.dstifp = ifp;
memcpy(&scr->dst,&dr->dst,dr->dst.sa.sa_len);
update_mtu(sc);
return(0);
@@ -436,23 +611,29 @@
{ unsigned int f;
if (! (flag & FWRITE)) return(EBADF);
f = *(unsigned int *)data & SSF_UCHG;
+ simple_lock(&gblf_lock);
global_flags = (global_flags & ~SSF_UCHG) | (f & SSF_GLOBAL);
+ simple_unlock(&gblf_lock);
sc->flags = (sc->flags & ~SSF_UCHG) | (f & ~SSF_GLOBAL);
}
return(0);
break;
case SRT_GFLAGS:
if (! (flag & FREAD)) return(EBADF);
+ simple_lock(&gblf_lock);
*(unsigned int *)data = sc->flags | global_flags;
+ simple_unlock(&gblf_lock);
return(0);
break;
case SRT_SGFLAGS:
{ unsigned int o;
unsigned int n;
if ((flag & (FWRITE|FREAD)) != (FWRITE|FREAD)) return(EBADF);
+ simple_lock(&gblf_lock);
o = sc->flags | global_flags;
n = *(unsigned int *)data & SSF_UCHG;
global_flags = (global_flags & ~SSF_UCHG) | (n & SSF_GLOBAL);
+ simple_unlock(&gblf_lock);
sc->flags = (sc->flags & ~SSF_UCHG) | (n & ~SSF_GLOBAL);
*(unsigned int *)data = o;
}
@@ -465,15 +646,32 @@
return(ENOTTY);
}

+static int srt_ctl_ioctl(
+ dev_t dev,
+ u_long cmd,
+ caddr_t data,
+ int flag,
+ struct lwp *l )
+{
+ SOFTC *sc;
+ int err;
+ int unit;
+
+ unit = minor(dev);
+ if ((unit < 0) || (unit > SRT_MAXUNIT)) return(ENXIO);
+ simple_lock(&softcv_lock);
+ sc = softcv[unit];
+ if (! sc)
+ { simple_unlock(&softcv_lock);
+ return(ENXIO);
+ }
+ simple_lock(&sc->lock);
+ simple_unlock(&softcv_lock);
+ err = srt_ctl_ioctl_core(sc,cmd,data,flag,l);
+ simple_unlock(&sc->lock);
+ return(err);
+}
+
const struct cdevsw srt_cdevsw
- = { &srt_open,
- &srt_close,
- nullread,
- nullwrite,
- &srt_ioctl,
- nullstop,
- notty,
- nullpoll,
- nommap,
- nullkqfilter,
- D_OTHER };
+ = { &srt_ctl_open, &srt_ctl_close, &srt_ctl_read, &srt_ctl_write,
+ &srt_ctl_ioctl, nostop, notty, nullpoll, nommap, nokqfilter, D_OTHER };

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Loading...