summaryrefslogtreecommitdiffstats
path: root/cpukit/libnetworking
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2002-09-14 18:18:50 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2002-09-14 18:18:50 +0000
commitce2c216469083c54cd9047e0ace13fa737d8c084 (patch)
tree046d3850051b7eb7452d9c5b82b37044edf713dd /cpukit/libnetworking
parent2002-09-14 Joel Sherrill <joel@OARcorp.com> (diff)
downloadrtems-ce2c216469083c54cd9047e0ace13fa737d8c084.tar.bz2
2002-09-14 Vyacheslav V. Burdjanadze <wr@zelax.ru>
* kern/uipc_mbuf.c, sys/mbuf.h, netinet/udp_usrreq.c: Add optional UDP broadcast forwarding support. * netinet/Makefile.am: Defined FORWARD_PROTOCOL to enabled UDP broadcast forwarding.
Diffstat (limited to 'cpukit/libnetworking')
-rw-r--r--cpukit/libnetworking/ChangeLog7
-rw-r--r--cpukit/libnetworking/kern/uipc_mbuf.c50
-rw-r--r--cpukit/libnetworking/netinet/Makefile.am2
-rw-r--r--cpukit/libnetworking/netinet/udp_usrreq.c578
-rw-r--r--cpukit/libnetworking/sys/mbuf.h4
5 files changed, 602 insertions, 39 deletions
diff --git a/cpukit/libnetworking/ChangeLog b/cpukit/libnetworking/ChangeLog
index fdb0d3bba3..ff0764f11f 100644
--- a/cpukit/libnetworking/ChangeLog
+++ b/cpukit/libnetworking/ChangeLog
@@ -1,3 +1,10 @@
+2002-09-14 Vyacheslav V. Burdjanadze <wr@zelax.ru>
+
+ * kern/uipc_mbuf.c, sys/mbuf.h, netinet/udp_usrreq.c: Add
+ optional UDP broadcast forwarding support.
+ * netinet/Makefile.am: Defined FORWARD_PROTOCOL to enabled UDP
+ broadcast forwarding.
+
2002-09-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
* netinet/in_cksum.c: #include <string.h> for puts in generic
diff --git a/cpukit/libnetworking/kern/uipc_mbuf.c b/cpukit/libnetworking/kern/uipc_mbuf.c
index 17d2be6b26..4d97ea0bb0 100644
--- a/cpukit/libnetworking/kern/uipc_mbuf.c
+++ b/cpukit/libnetworking/kern/uipc_mbuf.c
@@ -354,9 +354,10 @@ nospace:
/*
* Copy data from an mbuf chain starting "off" bytes from the beginning,
- * continuing for "len" bytes, into the indicated buffer.
+ * continuing for "len" bytes, into the indicated buffer. Return -1 if requested
+ * size is bigger than available
*/
-void
+int
m_copydata(m, off, len, cp)
register struct mbuf *m;
register int off;
@@ -364,20 +365,36 @@ m_copydata(m, off, len, cp)
caddr_t cp;
{
register unsigned count;
+ struct mbuf *m0 = m;
if (off < 0 || len < 0)
panic("m_copydata");
while (off > 0) {
- if (m == 0)
- panic("m_copydata");
+ if (m == 0) {
+ /*printf("m_copydata: offset > mbuf length (");
+ while(m0) {
+ printf("[%d] ",m0->m_len);
+ m0 = m0->m_next;
+ }
+ printf(")\n");*/
+ return -1;
+ }
if (off < m->m_len)
break;
off -= m->m_len;
m = m->m_next;
}
while (len > 0) {
- if (m == 0)
- panic("m_copydata");
+ if (m == 0) {
+ /*printf("m_copydata: length > mbuf length (");
+ while(m0) {
+ printf("[%d] ",m0->m_len);
+ m0 = m0->m_next;
+ }
+ printf(")\n");*/
+
+ return -1;
+ }
count = min(m->m_len - off, len);
bcopy(mtod(m, caddr_t) + off, cp, count);
len -= count;
@@ -385,6 +402,7 @@ m_copydata(m, off, len, cp)
off = 0;
m = m->m_next;
}
+ return 0;
}
/*
@@ -699,7 +717,7 @@ m_devget(buf, totlen, off0, ifp, copy)
* starting "off" bytes from the beginning, extending the mbuf
* chain if necessary.
*/
-void
+int
m_copyback(m0, off, len, cp)
struct mbuf *m0;
register int off;
@@ -717,8 +735,10 @@ m_copyback(m0, off, len, cp)
totlen += mlen;
if (m->m_next == 0) {
n = m_getclr(M_DONTWAIT, m->m_type);
- if (n == 0)
- goto out;
+ if (n == 0) {
+ /*panic("m_copyback() : malformed chain\n");*/
+ return -1;
+ }
n->m_len = min(MLEN, len + off);
m->m_next = n;
}
@@ -732,17 +752,23 @@ m_copyback(m0, off, len, cp)
mlen += off;
off = 0;
totlen += mlen;
- if (len == 0)
+ if (len == 0) {
+ m->m_len = mlen;
break;
+ }
if (m->m_next == 0) {
n = m_get(M_DONTWAIT, m->m_type);
- if (n == 0)
- break;
+ if (n == 0) {
+ /*panic("m_copyback() : malformed chain 2\n");*/
+ return -1;
+ };
n->m_len = min(MLEN, len);
m->m_next = n;
}
+ m->m_len = mlen;
m = m->m_next;
}
out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
m->m_pkthdr.len = totlen;
+ return 0;
}
diff --git a/cpukit/libnetworking/netinet/Makefile.am b/cpukit/libnetworking/netinet/Makefile.am
index 4749377403..8eefdeb2e8 100644
--- a/cpukit/libnetworking/netinet/Makefile.am
+++ b/cpukit/libnetworking/netinet/Makefile.am
@@ -23,7 +23,7 @@ include $(top_srcdir)/../automake/lib.am
#
AM_CPPFLAGS += -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS -DDIAGNOSTIC \
- -DBOOTP_COMPAT
+ -DBOOTP_COMPAT -DFORWARD_PROTOCOL
$(LIB): $(OBJS)
$(make-library)
diff --git a/cpukit/libnetworking/netinet/udp_usrreq.c b/cpukit/libnetworking/netinet/udp_usrreq.c
index 16c5fce2df..0530def031 100644
--- a/cpukit/libnetworking/netinet/udp_usrreq.c
+++ b/cpukit/libnetworking/netinet/udp_usrreq.c
@@ -34,6 +34,7 @@
* $Id$
*/
+
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/systm.h>
@@ -49,6 +50,7 @@
#include <sys/syslog.h>
#include <net/if.h>
+#include <net/pf.h>
#include <net/route.h>
#include <netinet/in.h>
@@ -60,6 +62,10 @@
#include <netinet/ip_icmp.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
+#include <time.h>
+
+#undef malloc
+#undef free
/*
* UDP protocol implementation.
@@ -71,11 +77,57 @@ static int udpcksum = 1;
static int udpcksum = 0; /* XXX */
#endif
SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW,
- &udpcksum, 0, "");
+ &udpcksum, 0, "Calculate UDP checksum");
+
+
+#ifdef FORWARD_PROTOCOL
+
+static int
+udp_store(struct mbuf *m);
+
+static int
+udp_doutput(struct in_addr dst);
+
+
+/*
+ * To implement udp broadcast forwarding we should check ``broadcast storm''
+ * condition that can be caused if there is alternate ways between two subnets
+ * and efficiently cut such loops. This can be done by caching sensetive packet
+ * information and performing tests on it:
+ * 1. If we got packet that is not in our cache we pass this packet and
+ * add it into cache. If there is no room in cache - LRU packet is discarded
+ * 2. If we got packet that already in our cache we make it MRU and:
+ * We check ttl of ip packet - if it same or greater as in cache we just
+ * pass it. If it less - just drop this packet.
+ */
+
+#define MAXUDPCACHE 10 /* Seems to be reasonable size */
+#define UDPMAXEXPIRE 30 /* 30 sec expire cache */
+
+struct packet_cache {
+ unsigned8 pc_ttl; /* IP packet TTL */
+ unsigned16 pc_sum; /* UDP packet checksum */
+ struct in_addr pc_src; /* IP packet source address*/
+ struct udphdr pc_uh; /* UDP packet header */
+ time_t pc_time; /* Expiry value */
+ struct packet_cache *next , *prev;
+
+};
+
+static struct packet_cache *udp_cache = NULL;
+
+#endif
-static int log_in_vain = 0;
-SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW,
- &log_in_vain, 0, "");
+
+static u_long udp_sendspace = 9216; /* really max datagram size */
+ /* 40 1K datagrams */
+SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW,
+ &udp_sendspace, 0, "Maximum UDP datagram size");
+
+static u_long udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
+SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
+ &udp_recvspace, 0, "Maximum UDP receive buffer size");
+
static struct inpcbhead udb; /* from udp_var.h */
static struct inpcbinfo udbinfo;
@@ -84,9 +136,13 @@ static struct inpcbinfo udbinfo;
#define UDBHASHSIZE 64
#endif
- struct udpstat udpstat; /* from udp_var.h */
-SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RD,
- &udpstat, udpstat, "");
+/*
+ * UDP statistics
+ */
+struct udpstat udpstat;
+
+SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RW,
+ &udpstat, udpstat, "UDP statistic");
static struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET };
@@ -95,14 +151,226 @@ static int udp_output __P((struct inpcb *, struct mbuf *, struct mbuf *,
struct mbuf *));
static void udp_notify __P((struct inpcb *, int));
+
+/* Added by Vasilkov. This system call is used by snmp agent code.
+ *
+ */
+void udp_get_struct_udb (struct inpcbhead * strudb)
+{
+ memcpy ((char*)strudb, (char*)&udb, sizeof(struct inpcbhead));
+}
+
+
+/*
+ * Register sysctl's
+ */
+void
+sysctl_register_udp_usrreq() {
+
+ sysctl_register(_net_inet_udp,checksum);
+ sysctl_register(_net_inet_udp,maxdgram);
+ sysctl_register(_net_inet_udp,stats);
+ sysctl_register(_net_inet_udp,recvspace);
+}
+
void
udp_init()
{
LIST_INIT(&udb);
udbinfo.listhead = &udb;
udbinfo.hashbase = hashinit(UDBHASHSIZE, M_PCB, &udbinfo.hashmask);
+
+}
+
+#ifdef FORWARD_PROTOCOL
+static unsigned char udp_ports[65536/8];
+
+/*
+ * Enable/Disable udp port forwarding
+ */
+int udp_forward_port(int port,int forward) {
+
+ int byte = port/8;
+ int offset = port%8;
+
+ if (forward)
+ udp_ports[byte] |= (0x80 >> offset);
+ else
+ udp_ports[byte] &= ~(0x80 >> offset);
+
+ return 0;
+}
+
+/*
+ * Check if port should be forwarded
+ */
+static int udp_if_forward(int port) {
+
+ int byte = port/8;
+ int offset = port%8;
+
+ return (udp_ports[byte] & (0x80 >> offset));
+
+}
+
+/*
+ * Get packet_cache from mbuf
+ */
+static int udp_pc_from_m(struct packet_cache *pc, struct mbuf *m) {
+
+ struct ip *iph = mtod(m,struct ip *);
+ struct udphdr *uh = (struct udphdr *)((char *)iph + sizeof(struct ip));
+
+ pc->pc_ttl = iph->ip_ttl;
+ pc->pc_sum = uh->uh_sum;
+ pc->pc_src = iph->ip_src;
+ pc->pc_uh = *uh;
+ pc->pc_time = time(NULL) + UDPMAXEXPIRE;
+
+ return 0;
+}
+
+/*
+ * Make cache entry MRU
+ */
+static void udp_make_mru(struct packet_cache *pc) {
+
+ if (pc == udp_cache)
+ return ;
+
+ /* MRU it */
+ if (pc->prev) pc->prev->next = pc->next;
+ if (pc->next) pc->next->prev = pc->prev;
+
+ pc->prev = NULL;
+ pc->next = udp_cache;
+ udp_cache->prev = pc;
+ udp_cache = pc;
+
+ pc->pc_time = time(NULL) + UDPMAXEXPIRE;
+
+ /*
+ * HUGE FIXME: pc_sum should be strong checksum of udp data. md5 seems
+ * to be ok.
+ */
+
}
+
+/*
+ *
+ */
+#define UDP_PASS 0
+#define UDP_DROP 1
+
+static int udp_analyze(struct mbuf *m) {
+
+ time_t now;
+ struct packet_cache *pc,my,*empty = NULL;
+
+
+ /*
+ * If still no cache allocated - allocate it
+ */
+ if (!udp_cache) {
+ int i;
+
+ for (i=0;i<MAXUDPCACHE;i++) {
+ struct packet_cache *pc = malloc(sizeof(struct packet_cache));
+ if (pc) {
+ memset(pc,0,sizeof(struct packet_cache));
+ pc->next = udp_cache;
+ if (udp_cache) udp_cache->prev = pc;
+ udp_cache = pc;
+ }
+ }
+ }
+
+ /*
+ * If no memory - just drop packet
+ */
+ if (!udp_cache)
+ return UDP_DROP;
+
+ pc = udp_cache;
+ now = time(NULL);
+
+ udp_pc_from_m(&my,m);
+
+ if (my.pc_ttl <= IPTTLDEC)
+ return UDP_DROP;
+
+ while( pc ) {
+
+ if (pc->pc_ttl) { /*Non-empty entry*/
+ if (pc->pc_time < now) {
+ pc->pc_ttl = 0;
+ empty = pc;
+#ifdef FORWARD_DEBUG
+/* printf("Entry expired :%s, sum %lu\n",inet_ntoa(pc->pc_src),pc->pc_sum);*/
+#endif
+ }
+ else {
+ if ((pc->pc_sum == my.pc_sum) &&
+ (pc->pc_src.s_addr == my.pc_src.s_addr) &&
+ (pc->pc_uh.uh_dport == my.pc_uh.uh_dport) &&
+ (pc->pc_uh.uh_ulen == my.pc_uh.uh_ulen)) {
+
+#ifdef FORWARD_DEBUG
+/* printf("Cache HIT\n");*/
+#endif
+
+ udp_make_mru(pc);
+ if (pc->pc_ttl <= my.pc_ttl)
+ return UDP_PASS;
+
+#ifdef FORWARD_DEBUG
+/* printf("Loop detected!\n");*/
+#endif
+ return UDP_DROP;
+ }
+
+ }
+ }
+ else
+ empty = pc;
+
+ pc = pc->next;
+ }
+
+ /*
+ * If no free entry in cache - remove LRU entry
+ */
+ if (!empty) {
+
+#ifdef FORWARD_DEBUG
+/* printf("Cache full, removing LRU\n");*/
+#endif
+ empty = udp_cache;
+ while(empty->next)
+ empty = empty->next;
+
+ }
+
+ /* Cache it and make MRU */
+#ifdef FORWARD_DEBUG
+/* printf("Caching packet\n");*/
+#endif
+ udp_make_mru(empty);
+
+ empty->pc_ttl = my.pc_ttl;
+ empty->pc_sum = my.pc_sum;
+ empty->pc_src = my.pc_src;
+ empty->pc_uh = my.pc_uh;
+ empty->pc_time = my.pc_time;
+
+ return UDP_PASS;
+}
+
+
+
+#endif /* FORWARD_PROTOCOL */
+
void
udp_input(m, iphlen)
register struct mbuf *m;
@@ -114,6 +382,22 @@ udp_input(m, iphlen)
struct mbuf *opts = 0;
int len;
struct ip save_ip;
+ struct ifnet *ifp = m->m_pkthdr.rcvif;
+ int log_in_vain = 0;
+ int blackhole = 0;
+
+
+ /*
+ * Fetch logging flag from interface
+ */
+ if (ifp->if_ip.ifi_udp & IFNET_UDP_LOG_IN_VAIN)
+ log_in_vain = 1;
+
+ /*
+ * Check if we should silently discard refused connects
+ */
+ if (ifp->if_ip.ifi_udp & IFNET_UDP_BLACKHOLE)
+ blackhole = 1;
udpstat.udps_ipackets++;
@@ -139,7 +423,15 @@ udp_input(m, iphlen)
}
ip = mtod(m, struct ip *);
}
- uh = (struct udphdr *)((caddr_t)ip + iphlen);
+ uh = (struct udphdr *)((caddr_t)ip + iphlen);
+
+#ifdef FORWARD_PROTOCOL
+ if (udp_if_forward(ntohs(uh->uh_dport))) {
+ if (in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif))
+ udp_store(m);
+ }
+#endif
+
/*
* Make mbuf data length reflect UDP length.
@@ -163,7 +455,9 @@ udp_input(m, iphlen)
/*
* Checksum extended UDP header and data.
*/
+
if (uh->uh_sum) {
+
((struct ipovly *)ip)->ih_next = 0;
((struct ipovly *)ip)->ih_prev = 0;
((struct ipovly *)ip)->ih_x1 = 0;
@@ -179,6 +473,105 @@ udp_input(m, iphlen)
if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
struct inpcb *last;
+
+#ifdef FORWARD_PROTOCOL
+ /*
+ * If our router configured to route broadcasts (this may
+ * be required to enable NetBIOS thru router)
+ */
+
+ if (udp_if_forward(ntohs(uh->uh_dport))) {
+ /*
+ * For each interface that allow directed broadcast
+ * we should reflect this packet with destanation address
+ * equal to interface subnet broadcast address
+ */
+ struct ifnet *ifp = ifnet;
+
+ /*
+ * Checksum udp data + header without address information
+ */
+ m->m_len -= sizeof(struct ip);
+ m->m_data += sizeof(struct ip);
+ uh->uh_sum = in_cksum(m, len/* + sizeof (struct ip)*/);
+ m->m_len += sizeof(struct ip);
+ m->m_data -= sizeof(struct ip);
+
+ *ip = save_ip;
+
+ if (udp_analyze(m) == UDP_DROP) {
+#ifdef FORWARD_DEBUG
+ printf("UDP DROP <%s:%d>, ttl=%d, sum=%lu\n",inet_ntoa(ip->ip_src),uh->uh_sport,ip->ip_ttl,uh->uh_sum);
+#endif
+ goto bad;
+
+ }
+
+#ifdef FORWARD_DEBUG
+ printf("UDP PASS <%s:%d>, ttl=%d, sum=%lu\n",inet_ntoa(ip->ip_src),uh->uh_sport,ip->ip_ttl,uh->uh_sum);
+#endif
+
+
+ while (ifp) {
+
+ if ((ifp != m->m_pkthdr.rcvif) &&
+ !(ifp->if_flags & IFF_LOOPBACK) /*&&
+ (ifp->if_ip.ifi_udp & IFNET_UDP_FORWARD_PROTOCOL)*/) {
+
+ struct ifaddr *ifa = ifp->if_addrlist;
+
+#ifdef FORWARD_DEBUG
+ /*printf("\tForwarding through %s%d\n",ifp->if_name,ifp->if_unit);*/
+#endif
+
+ while(ifa) {
+
+
+ if (ifa->ifa_addr->sa_family == AF_INET) {
+
+
+
+ if (ifp->if_flags | IFF_BROADCAST) {
+ if (ifa->ifa_dstaddr)
+ ip->ip_dst.s_addr = ((struct sockaddr_in *)(ifa->ifa_dstaddr))->sin_addr.s_addr;
+ else {
+ ip->ip_dst.s_addr = ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr;
+ ip->ip_dst.s_addr &= ((struct sockaddr_in *)(ifa->ifa_netmask))->sin_addr.s_addr;
+ ip->ip_dst.s_addr |= ~(((struct sockaddr_in *)(ifa->ifa_netmask))->sin_addr.s_addr);
+ }
+ }
+ else
+ goto bad;
+
+ /*Calculate correct UDP checksum*/
+
+
+#ifdef FORWARD_DEBUG
+ printf("\t\tForwarding to %s\n",inet_ntoa(ip->ip_dst));
+#endif
+ udp_doutput(ip->ip_dst);
+
+ }
+
+ ifa = ifa->ifa_next;
+ }
+ }
+ ifp = ifp->if_next;
+ }
+
+ if (opts)
+ m_freem(opts);
+ if (m)
+ m_freem(m);
+
+ /*
+ * FIXME: should I also pass udp packet to socket?
+ */
+
+ return ;
+ }
+#endif /* FORWARD_PROTOCOL */
+
/*
* Deliver a multicast or broadcast datagram to *all* sockets
* for which the local and remote addresses and ports match
@@ -260,6 +653,7 @@ udp_input(m, iphlen)
* (No need to send an ICMP Port Unreachable
* for a broadcast or multicast datgram.)
*/
+ udpstat.udps_noport++;
udpstat.udps_noportbcast++;
goto bad;
}
@@ -282,13 +676,16 @@ udp_input(m, iphlen)
ip->ip_dst, uh->uh_dport, 1);
if (inp == NULL) {
if (log_in_vain) {
- char buf[4*sizeof "123"];
+ char bufdst[20];
+ char bufsrc[20];
+
+ inet_ntop(AF_INET,&(ip->ip_dst),bufdst,sizeof(bufdst));
+ inet_ntop(AF_INET,&(ip->ip_src),bufdst,sizeof(bufsrc));
- strcpy(buf, inet_ntoa(ip->ip_dst));
log(LOG_INFO, "Connection attempt to UDP %s:%d"
" from %s:%d\n",
- buf, ntohs(uh->uh_dport),
- inet_ntoa(ip->ip_src), ntohs(uh->uh_sport));
+ bufdst, ntohs(uh->uh_dport),
+ bufsrc, ntohs(uh->uh_sport));
}
udpstat.udps_noport++;
if (m->m_flags & (M_BCAST | M_MCAST)) {
@@ -296,6 +693,13 @@ udp_input(m, iphlen)
goto bad;
}
*ip = save_ip;
+
+ /*
+ * If we forced to be silent as much as possible..
+ */
+ if (blackhole)
+ goto bad;
+
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
return;
}
@@ -323,7 +727,7 @@ udp_input(m, iphlen)
bad:
m_freem(m);
if (opts)
- m_freem(opts);
+ m_freem(opts);
}
/*
@@ -431,7 +835,7 @@ udp_output(inp, m, addr, control)
* Stuff checksum and output datagram.
*/
ui->ui_sum = 0;
- if (udpcksum) {
+ if (udpcksum) { /*FIXME: should be taken from ouput interface */
if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
ui->ui_sum = 0xffff;
}
@@ -441,7 +845,7 @@ udp_output(inp, m, addr, control)
udpstat.udps_opackets++;
error = ip_output(m, inp->inp_options, &inp->inp_route,
inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
- inp->inp_moptions);
+ inp->inp_moptions,0);
if (addr) {
in_pcbdisconnect(inp);
@@ -455,14 +859,6 @@ release:
return (error);
}
-static u_long udp_sendspace = 9216; /* really max datagram size */
- /* 40 1K datagrams */
-SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW,
- &udp_sendspace, 0, "");
-
-static u_long udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
-SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
- &udp_recvspace, 0, "");
/*ARGSUSED*/
int
@@ -501,7 +897,7 @@ udp_usrreq(so, req, m, addr, control)
error = soreserve(so, udp_sendspace, udp_recvspace);
if (error)
break;
- ((struct inpcb *) so->so_pcb)->inp_ip_ttl = ip_defttl;
+ ((struct inpcb *) so->so_pcb)->inp_ip_ttl = ip_defttl; /*FIXME: fetch ttl from interface first*/
break;
case PRU_DETACH:
@@ -611,3 +1007,137 @@ udp_detach(inp)
in_pcbdetach(inp);
splx(s);
}
+
+#ifdef FORWARD_PROTOCOL
+
+static int ttl;
+static struct in_addr src;
+static int sport,dport;
+static char buf[8096];
+static int len;
+
+/*
+ * Store packet
+ */
+static int
+udp_store(struct mbuf *m) {
+
+ struct ip *iph = mtod(m,struct ip *);
+ struct udphdr *uh = iph + 1;
+
+#ifdef FORWARD_DEBUG
+ printf("Storing %d bytes at offset %d of total packet len %d\n",uh->uh_ulen - sizeof(struct udphdr),sizeof(struct ip) + sizeof(struct udphdr),m->m_pkthdr.len);
+#endif
+
+ if (m_copydata(m,sizeof(struct ip) + sizeof(struct udphdr),
+ uh->uh_ulen - sizeof(struct udphdr),
+ buf)<0) {
+ ttl = 0;
+ return -1;
+ }
+
+
+ ttl = iph->ip_ttl;
+ src = iph->ip_src;
+ sport = uh->uh_sport;
+ dport = uh->uh_dport;
+ len = uh->uh_ulen - sizeof(struct udphdr);
+
+ return 0;
+}
+
+/*
+ * Pull packet to network
+ */
+static int
+udp_doutput(struct in_addr dst) {
+
+
+ struct udpiphdr *ui;
+ struct mbuf *m;
+ int error;
+ struct route ro;
+
+ if (ttl <= 1)
+ return -1;
+
+ m = m_gethdr(M_DONTWAIT,MT_DATA);
+
+ if (!m) {
+#ifdef FORWARD_DEBUG
+ printf("udp_doutput() : No buffers available\n");
+#endif
+ return -1;
+ }
+
+ m->m_pkthdr.len = 0;
+ m->m_pkthdr.rcvif = NULL;
+ m->m_len = MHLEN;
+
+ if (m_copyback(m,0,len,buf)<0) {
+ m_freem(m);
+ return -1;
+ }
+
+ M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
+
+ if (!m) {
+#ifdef FORWARD_DEBUG
+ printf("udp_douptut() : No buffers available\n");
+#endif
+ return -1;
+ }
+
+ /*
+ * Fill in mbuf with extended UDP header
+ * and addresses and length put into network format.
+ */
+ ui = mtod(m, struct udpiphdr *);
+ ui->ui_next = ui->ui_prev = 0;
+ ui->ui_x1 = 0;
+ ui->ui_pr = IPPROTO_UDP;
+ ui->ui_len = htons((u_short)len + sizeof (struct udphdr));
+ ui->ui_src = src;
+ ui->ui_dst = dst;
+ ui->ui_sport = sport;
+ ui->ui_dport = dport;
+ ui->ui_ulen = ui->ui_len;
+
+ /*
+ * Stuff checksum and output datagram.
+ */
+ ui->ui_sum = 0;
+ if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
+ ui->ui_sum = 0xffff;
+
+
+ ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
+ ((struct ip *)ui)->ip_ttl = ttl - 1;
+ ((struct ip *)ui)->ip_tos = 0;
+
+ bzero(&ro, sizeof ro);
+
+ udpstat.udps_opackets++;
+
+#ifdef FORWARD_DEBUG
+ {
+ struct mbuf *n = m;
+ printf("Sending buffer chain: ");
+ while (n) {
+ printf("[%d] ",n->m_len);
+ n = n->m_next;
+ }
+ printf("\n");
+
+ }
+#endif
+
+ error = ip_output(m, NULL, &ro,IP_ALLOWBROADCAST,NULL,0);
+
+ if (ro.ro_rt)
+ RTFREE(ro.ro_rt);
+
+ return error;
+}
+
+#endif /* FORWARD_PROTOCOL */
diff --git a/cpukit/libnetworking/sys/mbuf.h b/cpukit/libnetworking/sys/mbuf.h
index 00f8a13a5c..5bc97c742b 100644
--- a/cpukit/libnetworking/sys/mbuf.h
+++ b/cpukit/libnetworking/sys/mbuf.h
@@ -407,8 +407,8 @@ void m_adj __P((struct mbuf *, int));
void m_cat __P((struct mbuf *,struct mbuf *));
int m_mballoc __P((int, int));
int m_clalloc __P((int, int));
-void m_copyback __P((struct mbuf *, int, int, caddr_t));
-void m_copydata __P((struct mbuf *,int,int,caddr_t));
+int m_copyback __P((struct mbuf *, int, int, caddr_t));
+int m_copydata __P((struct mbuf *, int, int, caddr_t));
void m_freem __P((struct mbuf *));
void m_reclaim __P((void));