From ce2c216469083c54cd9047e0ace13fa737d8c084 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Sat, 14 Sep 2002 18:18:50 +0000 Subject: 2002-09-14 Vyacheslav V. Burdjanadze * 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. --- cpukit/libnetworking/ChangeLog | 7 + cpukit/libnetworking/kern/uipc_mbuf.c | 50 ++- cpukit/libnetworking/netinet/Makefile.am | 2 +- cpukit/libnetworking/netinet/udp_usrreq.c | 578 ++++++++++++++++++++++++++++-- cpukit/libnetworking/sys/mbuf.h | 4 +- 5 files changed, 602 insertions(+), 39 deletions(-) (limited to 'cpukit/libnetworking') 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 + + * 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 * netinet/in_cksum.c: #include 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 #include #include @@ -49,6 +50,7 @@ #include #include +#include #include #include @@ -60,6 +62,10 @@ #include #include #include +#include + +#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;inext = 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)); -- cgit v1.2.3