Index: head/lib/libstand/Makefile =================================================================== --- head/lib/libstand/Makefile (revision 318319) +++ head/lib/libstand/Makefile (revision 318320) @@ -1,163 +1,163 @@ # $FreeBSD$ # Originally from $NetBSD: Makefile,v 1.21 1997/10/26 22:08:38 lukem Exp $ # # Notes: # - We don't use the libc strerror/sys_errlist because the string table is # quite large. # PACKAGE=lib${LIB} MK_PROFILE= no MK_SSP= no .include LIBSTAND_SRC?= ${.CURDIR} LIBSTAND_CPUARCH?=${MACHINE_CPUARCH} LIBC_SRC= ${LIBSTAND_SRC}/../libc LIB= stand NO_PIC= INCS?= stand.h MAN?= libstand.3 WARNS?= 0 CFLAGS+= -I${LIBSTAND_SRC} # standalone components and stuff we have modified locally SRCS+= gzguts.h zutil.h __main.c assert.c bcd.c environment.c getopt.c gets.c \ globals.c pager.c printf.c strdup.c strerror.c strtol.c strtoul.c random.c \ sbrk.c twiddle.c zalloc.c zalloc_malloc.c # private (pruned) versions of libc string functions SRCS+= strcasecmp.c .PATH: ${LIBC_SRC}/net SRCS+= ntoh.c # string functions from libc .PATH: ${LIBC_SRC}/string SRCS+= bcmp.c bcopy.c bzero.c ffs.c fls.c \ memccpy.c memchr.c memcmp.c memcpy.c memmove.c memset.c \ qdivrem.c strcat.c strchr.c strcmp.c strcpy.c \ strcspn.c strlcat.c strlcpy.c strlen.c strncat.c strncmp.c strncpy.c \ strpbrk.c strrchr.c strsep.c strspn.c strstr.c strtok.c swab.c .if ${MACHINE_CPUARCH} == "arm" .PATH: ${LIBC_SRC}/arm/gen # Do not generate movt/movw, because the relocation fixup for them does not # translate to the -Bsymbolic -pie format required by self_reloc() in loader(8). # Also, the fpu is not available in a standalone environment. .if ${COMPILER_VERSION} < 30800 CFLAGS.clang+= -mllvm -arm-use-movt=0 .else CFLAGS.clang+= -mno-movt .endif CFLAGS.clang+= -mfpu=none # Compiler support functions .PATH: ${LIBSTAND_SRC}/../../contrib/compiler-rt/lib/builtins/ # __clzsi2 and ctzsi2 for various builtin functions SRCS+= clzsi2.c ctzsi2.c # Divide and modulus functions called by the compiler SRCS+= divmoddi4.c divmodsi4.c divdi3.c divsi3.c moddi3.c modsi3.c SRCS+= udivmoddi4.c udivmodsi4.c udivdi3.c udivsi3.c umoddi3.c umodsi3.c .PATH: ${LIBSTAND_SRC}/../../contrib/compiler-rt/lib/builtins/arm/ SRCS+= aeabi_idivmod.S aeabi_ldivmod.S aeabi_uidivmod.S aeabi_uldivmod.S SRCS+= aeabi_memcmp.S aeabi_memcpy.S aeabi_memmove.S aeabi_memset.S .endif .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "riscv" .PATH: ${LIBC_SRC}/${MACHINE_CPUARCH}/gen .endif .if ${MACHINE_CPUARCH} == "powerpc" .PATH: ${LIBC_SRC}/quad SRCS+= ashldi3.c ashrdi3.c SRCS+= syncicache.c .endif # uuid functions from libc .PATH: ${LIBC_SRC}/uuid SRCS+= uuid_create_nil.c uuid_equal.c uuid_from_string.c uuid_is_nil.c uuid_to_string.c # _setjmp/_longjmp .PATH: ${LIBSTAND_SRC}/${LIBSTAND_CPUARCH} SRCS+= _setjmp.S # decompression functionality from libbz2 # NOTE: to actually test this functionality after libbz2 upgrade compile # loader(8) with LOADER_BZIP2_SUPPORT defined .PATH: ${LIBSTAND_SRC}/../../contrib/bzip2 CFLAGS+= -DBZ_NO_STDIO -DBZ_NO_COMPRESS SRCS+= libstand_bzlib_private.h .for file in bzlib.c crctable.c decompress.c huffman.c randtable.c SRCS+= _${file} CLEANFILES+= _${file} _${file}: ${file} sed "s|bzlib_private\.h|libstand_bzlib_private.h|" \ ${.ALLSRC} > ${.TARGET} .endfor CLEANFILES+= libstand_bzlib_private.h libstand_bzlib_private.h: bzlib_private.h sed -e 's||"stand.h"|' \ ${.ALLSRC} > ${.TARGET} # decompression functionality from zlib .PATH: ${LIBSTAND_SRC}/../../contrib/zlib CFLAGS+=-DHAVE_MEMCPY -I${LIBSTAND_SRC}/../../contrib/zlib SRCS+= adler32.c crc32.c libstand_zutil.h libstand_gzguts.h .for file in infback.c inffast.c inflate.c inftrees.c zutil.c SRCS+= _${file} CLEANFILES+= _${file} _${file}: ${file} sed -e "s|zutil\.h|libstand_zutil.h|" \ -e "s|gzguts\.h|libstand_gzguts.h|" \ ${.ALLSRC} > ${.TARGET} .endfor # depend on stand.h being able to be included multiple times .for file in zutil.h gzguts.h CLEANFILES+= libstand_${file} libstand_${file}: ${file} sed -e 's||"stand.h"|' \ -e 's||"stand.h"|' \ -e 's||"stand.h"|' \ -e 's||"stand.h"|' \ -e 's||"stand.h"|' \ ${.ALLSRC} > ${.TARGET} .endfor # io routines SRCS+= closeall.c dev.c ioctl.c nullfs.c stat.c \ fstat.c close.c lseek.c open.c read.c write.c readdir.c # network routines -SRCS+= arp.c ether.c inet_ntoa.c in_cksum.c net.c udp.c netif.c rpc.c +SRCS+= arp.c ether.c ip.c inet_ntoa.c in_cksum.c net.c udp.c netif.c rpc.c # network info services: SRCS+= bootp.c rarp.c bootparam.c # boot filesystems SRCS+= ufs.c nfs.c cd9660.c tftp.c gzipfs.c bzipfs.c SRCS+= dosfs.c ext2fs.c SRCS+= splitfs.c SRCS+= pkgfs.c .if ${MK_NAND} != "no" SRCS+= nandfs.c .endif # explicit_bzero .PATH: ${SRCTOP}/sys/libkern SRCS+= explicit_bzero.c .include .include Index: head/lib/libstand/ip.c =================================================================== --- head/lib/libstand/ip.c (nonexistent) +++ head/lib/libstand/ip.c (revision 318320) @@ -0,0 +1,422 @@ +/* + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * The send and receive functions were originally implemented in udp.c and + * moved here. Also it is likely some more cleanup can be done, especially + * once we will implement the support for tcp. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "stand.h" +#include "net.h" + +typedef STAILQ_HEAD(ipqueue, ip_queue) ip_queue_t; +struct ip_queue { + void *ipq_pkt; + struct ip *ipq_hdr; + STAILQ_ENTRY(ip_queue) ipq_next; +}; + +/* + * Fragment re-assembly queue. + */ +struct ip_reasm { + struct in_addr ip_src; + struct in_addr ip_dst; + uint16_t ip_id; + uint8_t ip_proto; + uint8_t ip_ttl; + size_t ip_total_size; + ip_queue_t ip_queue; + void *ip_pkt; + struct ip *ip_hdr; + STAILQ_ENTRY(ip_reasm) ip_next; +}; + +STAILQ_HEAD(ire_list, ip_reasm) ire_list = STAILQ_HEAD_INITIALIZER(ire_list); + +/* Caller must leave room for ethernet and ip headers in front!! */ +ssize_t +sendip(struct iodesc *d, void *pkt, size_t len, uint8_t proto) +{ + ssize_t cc; + struct ip *ip; + u_char *ea; + +#ifdef NET_DEBUG + if (debug) { + printf("sendip: proto: %x d=%p called.\n", proto, (void *)d); + if (d) { + printf("saddr: %s:%d", + inet_ntoa(d->myip), ntohs(d->myport)); + printf(" daddr: %s:%d\n", + inet_ntoa(d->destip), ntohs(d->destport)); + } + } +#endif + + ip = (struct ip *)pkt - 1; + len += sizeof(*ip); + + bzero(ip, sizeof(*ip)); + + ip->ip_v = IPVERSION; /* half-char */ + ip->ip_hl = sizeof(*ip) >> 2; /* half-char */ + ip->ip_len = htons(len); + ip->ip_p = proto; /* char */ + ip->ip_ttl = IPDEFTTL; /* char */ + ip->ip_src = d->myip; + ip->ip_dst = d->destip; + ip->ip_sum = in_cksum(ip, sizeof(*ip)); /* short, but special */ + + if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_src.s_addr == 0 || + netmask == 0 || SAMENET(ip->ip_src, ip->ip_dst, netmask)) + ea = arpwhohas(d, ip->ip_dst); + else + ea = arpwhohas(d, gateip); + + cc = sendether(d, ip, len, ea, ETHERTYPE_IP); + if (cc == -1) + return (-1); + if (cc != len) + panic("sendip: bad write (%zd != %zd)", cc, len); + return (cc - sizeof(*ip)); +} + +static void +ip_reasm_free(struct ip_reasm *ipr) +{ + struct ip_queue *ipq; + + while ((ipq = STAILQ_FIRST(&ipr->ip_queue)) != NULL) { + STAILQ_REMOVE_HEAD(&ipr->ip_queue, ipq_next); + free(ipq->ipq_pkt); + free(ipq); + } + free(ipr->ip_pkt); + free(ipr); +} + +static int +ip_reasm_add(struct ip_reasm *ipr, void *pkt, struct ip *ip) +{ + struct ip_queue *ipq, *prev, *p; + + if ((ipq = calloc(1, sizeof (*ipq))) == NULL) + return (1); + + ipq->ipq_pkt = pkt; + ipq->ipq_hdr = ip; + + prev = NULL; + STAILQ_FOREACH(p, &ipr->ip_queue, ipq_next) { + if ((ntohs(p->ipq_hdr->ip_off) & IP_OFFMASK) < + (ntohs(ip->ip_off) & IP_OFFMASK)) { + prev = p; + continue; + } + if (prev == NULL) + break; + + STAILQ_INSERT_AFTER(&ipr->ip_queue, prev, ipq, ipq_next); + return (0); + } + STAILQ_INSERT_HEAD(&ipr->ip_queue, ipq, ipq_next); + return (0); +} + +/* + * Receive a IP packet and validate it is for us. + */ +static ssize_t +readipv4(struct iodesc *d, void **pkt, void **payload, time_t tleft, + uint8_t proto) +{ + ssize_t n; + size_t hlen; + struct ether_header *eh; + struct ip *ip; + struct udphdr *uh; + uint16_t etype; /* host order */ + char *ptr; + struct ip_reasm *ipr; + struct ip_queue *ipq, *last; + +#ifdef NET_DEBUG + if (debug) + printf("readip: called\n"); +#endif + + ip = NULL; + ptr = NULL; + n = readether(d, (void **)&ptr, (void **)&ip, tleft, &etype); + if (n == -1 || n < sizeof(*ip) + sizeof(*uh)) { + free(ptr); + return (-1); + } + + /* Ethernet address checks now in readether() */ + + /* Need to respond to ARP requests. */ + if (etype == ETHERTYPE_ARP) { + struct arphdr *ah = (void *)ip; + if (ah->ar_op == htons(ARPOP_REQUEST)) { + /* Send ARP reply */ + arp_reply(d, ah); + } + free(ptr); + errno = EAGAIN; /* Call me again. */ + return (-1); + } + + if (etype != ETHERTYPE_IP) { +#ifdef NET_DEBUG + if (debug) + printf("readip: not IP. ether_type=%x\n", etype); +#endif + free(ptr); + return (-1); + } + + /* Check ip header */ + if (ip->ip_v != IPVERSION || + ip->ip_p != proto) { /* half char */ +#ifdef NET_DEBUG + if (debug) { + printf("readip: IP version or proto. ip_v=%d ip_p=%d\n", + ip->ip_v, ip->ip_p); + } +#endif + free(ptr); + return (-1); + } + + hlen = ip->ip_hl << 2; + if (hlen < sizeof(*ip) || + in_cksum(ip, hlen) != 0) { +#ifdef NET_DEBUG + if (debug) + printf("readip: short hdr or bad cksum.\n"); +#endif + free(ptr); + return (-1); + } + if (n < ntohs(ip->ip_len)) { +#ifdef NET_DEBUG + if (debug) + printf("readip: bad length %d < %d.\n", + (int)n, ntohs(ip->ip_len)); +#endif + free(ptr); + return (-1); + } + if (d->myip.s_addr && ip->ip_dst.s_addr != d->myip.s_addr) { +#ifdef NET_DEBUG + if (debug) { + printf("readip: bad saddr %s != ", inet_ntoa(d->myip)); + printf("%s\n", inet_ntoa(ip->ip_dst)); + } +#endif + free(ptr); + return (-1); + } + + /* Unfragmented packet. */ + if ((ntohs(ip->ip_off) & IP_MF) == 0 && + (ntohs(ip->ip_off) & IP_OFFMASK) == 0) { + uh = (struct udphdr *)((uintptr_t)ip + sizeof (*ip)); + /* If there were ip options, make them go away */ + if (hlen != sizeof(*ip)) { + bcopy(((u_char *)ip) + hlen, uh, uh->uh_ulen - hlen); + ip->ip_len = htons(sizeof(*ip)); + n -= hlen - sizeof(*ip); + } + + n = (n > (ntohs(ip->ip_len) - sizeof(*ip))) ? + ntohs(ip->ip_len) - sizeof(*ip) : n; + *pkt = ptr; + *payload = (void *)((uintptr_t)ip + sizeof(*ip)); + return (n); + } + + STAILQ_FOREACH(ipr, &ire_list, ip_next) { + if (ipr->ip_src.s_addr == ip->ip_src.s_addr && + ipr->ip_dst.s_addr == ip->ip_dst.s_addr && + ipr->ip_id == ip->ip_id && + ipr->ip_proto == ip->ip_p) + break; + } + + /* Allocate new reassembly entry */ + if (ipr == NULL) { + if ((ipr = calloc(1, sizeof (*ipr))) == NULL) { + free(ptr); + return (-1); + } + + ipr->ip_src = ip->ip_src; + ipr->ip_dst = ip->ip_dst; + ipr->ip_id = ip->ip_id; + ipr->ip_proto = ip->ip_p; + ipr->ip_ttl = MAXTTL; + STAILQ_INIT(&ipr->ip_queue); + STAILQ_INSERT_TAIL(&ire_list, ipr, ip_next); + } + + if (ip_reasm_add(ipr, ptr, ip) != 0) { + STAILQ_REMOVE(&ire_list, ipr, ip_reasm, ip_next); + free(ipr); + free(ptr); + return (-1); + } + + if ((ntohs(ip->ip_off) & IP_MF) == 0) { + ipr->ip_total_size = (8 * (ntohs(ip->ip_off) & IP_OFFMASK)); + ipr->ip_total_size += n + sizeof (*ip); + ipr->ip_total_size += sizeof (struct ether_header); + + ipr->ip_pkt = malloc(ipr->ip_total_size + 2); + if (ipr->ip_pkt == NULL) { + STAILQ_REMOVE(&ire_list, ipr, ip_reasm, ip_next); + ip_reasm_free(ipr); + return (-1); + } + } + + /* + * If we do not have re-assembly buffer ipr->ip_pkt, we are still + * missing fragments, so just restart the read. + */ + if (ipr->ip_pkt == NULL) { + errno = EAGAIN; + return (-1); + } + + /* + * Walk the packet list in reassembly queue, if we got all the + * fragments, build the packet. + */ + n = 0; + last = NULL; + STAILQ_FOREACH(ipq, &ipr->ip_queue, ipq_next) { + if ((ntohs(ipq->ipq_hdr->ip_off) & IP_OFFMASK) != n / 8) { + errno = EAGAIN; + return (-1); + } + + n += ntohs(ipq->ipq_hdr->ip_len) - (ipq->ipq_hdr->ip_hl << 2); + last = ipq; + } + if ((ntohs(last->ipq_hdr->ip_off) & IP_MF) != 0) { + errno = EAGAIN; + return (-1); + } + + ipq = STAILQ_FIRST(&ipr->ip_queue); + /* Fabricate ethernet header */ + eh = (struct ether_header *)((uintptr_t)ipr->ip_pkt + 2); + bcopy((void *)((uintptr_t)ipq->ipq_pkt + 2), eh, sizeof (*eh)); + + /* Fabricate IP header */ + ipr->ip_hdr = (struct ip *)((uintptr_t)eh + sizeof (*eh)); + bcopy(ipq->ipq_hdr, ipr->ip_hdr, sizeof (*ipr->ip_hdr)); + ipr->ip_hdr->ip_hl = sizeof (*ipr->ip_hdr) >> 2; + ipr->ip_hdr->ip_len = htons(n); + ipr->ip_hdr->ip_sum = 0; + ipr->ip_hdr->ip_sum = in_cksum(ipr->ip_hdr, sizeof (*ipr->ip_hdr)); + + n = 0; + ptr = (char *)((uintptr_t)ipr->ip_hdr + sizeof (*ipr->ip_hdr)); + STAILQ_FOREACH(ipq, &ipr->ip_queue, ipq_next) { + char *data; + size_t len; + + hlen = ipq->ipq_hdr->ip_hl << 2; + len = ntohs(ipq->ipq_hdr->ip_len) - hlen; + data = (char *)((uintptr_t)ipq->ipq_hdr + hlen); + + bcopy(data, ptr + n, len); + n += len; + } + + *pkt = ipr->ip_pkt; + ipr->ip_pkt = NULL; /* Avoid free from ip_reasm_free() */ + *payload = ptr; + + /* Clean up the reassembly list */ + while ((ipr = STAILQ_FIRST(&ire_list)) != NULL) { + STAILQ_REMOVE_HEAD(&ire_list, ip_next); + ip_reasm_free(ipr); + } + return (n); +} + +/* + * Receive a IP packet. + */ +ssize_t +readip(struct iodesc *d, void **pkt, void **payload, time_t tleft, + uint8_t proto) +{ + time_t t; + ssize_t ret = -1; + + t = getsecs(); + while ((getsecs() - t) < tleft) { + errno = 0; + ret = readipv4(d, pkt, payload, tleft, proto); + if (errno != EAGAIN) + break; + } + return (ret); +} Property changes on: head/lib/libstand/ip.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/lib/libstand/net.h =================================================================== --- head/lib/libstand/net.h (revision 318319) +++ head/lib/libstand/net.h (revision 318320) @@ -1,131 +1,133 @@ /* $NetBSD: net.h,v 1.10 1995/10/20 00:46:30 cgd Exp $ */ /* * Copyright (c) 1993 Adam Glass * Copyright (c) 1992 Regents of the University of California. * All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _STAND_NET_H #define _STAND_NET_H #ifndef _KERNEL /* XXX - see */ #undef __IPADDR #define __IPADDR(x) htonl((u_int32_t)(x)) #endif #include "iodesc.h" #define BA { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } enum net_proto { NET_NONE, NET_NFS, NET_TFTP }; /* Returns true if n_long's on the same net */ #define SAMENET(a1, a2, m) ((a1.s_addr & m) == (a2.s_addr & m)) #define MACPY(s, d) bcopy((char *)s, (char *)d, 6) #define MAXTMO 120 /* seconds */ #define MINTMO 2 /* seconds */ #define FNAME_SIZE 128 #define IFNAME_SIZE 16 #define RECV_SIZE 1536 /* XXX delete this */ /* * How much room to leave for headers: * 14: struct ether_header * 20: struct ip * 8: struct udphdr * That's 42 but let's pad it out to 48 bytes. */ #define ETHER_SIZE 14 #define HEADER_SIZE 48 extern u_char bcea[6]; extern char rootpath[FNAME_SIZE]; extern char bootfile[FNAME_SIZE]; extern char hostname[FNAME_SIZE]; extern int hostnamelen; extern char domainname[FNAME_SIZE]; extern int domainnamelen; extern int netproto; extern char ifname[IFNAME_SIZE]; /* All of these are in network order. */ extern struct in_addr myip; extern struct in_addr rootip; extern struct in_addr swapip; extern struct in_addr gateip; extern struct in_addr nameip; extern n_long netmask; extern u_int intf_mtu; extern int debug; /* defined in the machdep sources */ extern struct iodesc sockets[SOPEN_MAX]; /* ARP/RevARP functions: */ u_char *arpwhohas(struct iodesc *, struct in_addr); void arp_reply(struct iodesc *, void *); int rarp_getipaddress(int); /* Link functions: */ ssize_t sendether(struct iodesc *d, void *pkt, size_t len, u_char *dea, int etype); ssize_t readether(struct iodesc *, void **, void **, time_t, uint16_t *); +ssize_t sendip(struct iodesc *, void *, size_t, uint8_t); +ssize_t readip(struct iodesc *, void **, void **, time_t, uint8_t); ssize_t sendudp(struct iodesc *, void *, size_t); ssize_t readudp(struct iodesc *, void **, void **, time_t); ssize_t sendrecv(struct iodesc *, ssize_t (*)(struct iodesc *, void *, size_t), void *, size_t, ssize_t (*)(struct iodesc *, void **, void **, time_t), void **, void **); /* bootp/DHCP */ void bootp(int, int); /* Utilities: */ char *ether_sprintf(u_char *); int in_cksum(void *, int); char *inet_ntoa(struct in_addr); char *intoa(n_long); /* similar to inet_ntoa */ n_long inet_addr(char *); /* Machine-dependent functions: */ time_t getsecs(void); #endif /* ! _STAND_NET_H */ Index: head/lib/libstand/udp.c =================================================================== --- head/lib/libstand/udp.c (revision 318319) +++ head/lib/libstand/udp.c (revision 318320) @@ -1,278 +1,180 @@ /* Taken from $NetBSD: net.c,v 1.20 1997/12/26 22:41:30 scottr Exp $ */ /* * Copyright (c) 1992 Regents of the University of California. * All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL) */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "stand.h" #include "net.h" /* Caller must leave room for ethernet, ip and udp headers in front!! */ ssize_t sendudp(struct iodesc *d, void *pkt, size_t len) { ssize_t cc; - struct ip *ip; + struct udpiphdr *ui; struct udphdr *uh; - u_char *ea; #ifdef NET_DEBUG if (debug) { printf("sendudp: d=%lx called.\n", (long)d); if (d) { printf("saddr: %s:%d", inet_ntoa(d->myip), ntohs(d->myport)); printf(" daddr: %s:%d\n", inet_ntoa(d->destip), ntohs(d->destport)); } } #endif + ui = (struct udpiphdr *)pkt - 1; + bzero(ui, sizeof(*ui)); + uh = (struct udphdr *)pkt - 1; - ip = (struct ip *)uh - 1; - len += sizeof(*ip) + sizeof(*uh); + len += sizeof(*uh); - bzero(ip, sizeof(*ip) + sizeof(*uh)); - - ip->ip_v = IPVERSION; /* half-char */ - ip->ip_hl = sizeof(*ip) >> 2; /* half-char */ - ip->ip_len = htons(len); - ip->ip_p = IPPROTO_UDP; /* char */ - ip->ip_ttl = IPDEFTTL; /* char */ - ip->ip_src = d->myip; - ip->ip_dst = d->destip; - ip->ip_sum = in_cksum(ip, sizeof(*ip)); /* short, but special */ - uh->uh_sport = d->myport; uh->uh_dport = d->destport; - uh->uh_ulen = htons(len - sizeof(*ip)); + uh->uh_ulen = htons(len); -#ifndef UDP_NO_CKSUM - { - struct udpiphdr *ui; - struct ip tip; + ui->ui_pr = IPPROTO_UDP; + ui->ui_len = uh->uh_ulen; + ui->ui_src = d->myip; + ui->ui_dst = d->destip; - /* Calculate checksum (must save and restore ip header) */ - tip = *ip; - ui = (struct udpiphdr *)ip; - bzero(&ui->ui_x1, sizeof(ui->ui_x1)); - ui->ui_len = uh->uh_ulen; - uh->uh_sum = in_cksum(ui, len); - *ip = tip; - } +#ifndef UDP_NO_CKSUM + uh->uh_sum = in_cksum(ui, len + sizeof (struct ip)); #endif - if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_src.s_addr == 0 || - netmask == 0 || SAMENET(ip->ip_src, ip->ip_dst, netmask)) - ea = arpwhohas(d, ip->ip_dst); - else - ea = arpwhohas(d, gateip); - - cc = sendether(d, ip, len, ea, ETHERTYPE_IP); + cc = sendip(d, uh, len, IPPROTO_UDP); if (cc == -1) return (-1); if (cc != len) panic("sendudp: bad write (%zd != %zd)", cc, len); - return (cc - (sizeof(*ip) + sizeof(*uh))); + return (cc - sizeof(*uh)); } /* * Receive a UDP packet and validate it is for us. */ ssize_t readudp(struct iodesc *d, void **pkt, void **payload, time_t tleft) { ssize_t n; - size_t hlen; - struct ip *ip; struct udphdr *uh; - uint16_t etype; /* host order */ void *ptr; #ifdef NET_DEBUG if (debug) printf("readudp: called\n"); #endif - ip = NULL; + uh = NULL; ptr = NULL; - n = readether(d, &ptr, (void **)&ip, tleft, &etype); - if (n == -1 || n < sizeof(*ip) + sizeof(*uh)) { + n = readip(d, &ptr, (void **)&uh, tleft, IPPROTO_UDP); + if (n == -1 || n < sizeof(*uh) || n != ntohs(uh->uh_ulen)) { free(ptr); return (-1); } - /* Ethernet address checks now in readether() */ - - /* Need to respond to ARP requests. */ - if (etype == ETHERTYPE_ARP) { - struct arphdr *ah = (void *)ip; - if (ah->ar_op == htons(ARPOP_REQUEST)) { - /* Send ARP reply */ - arp_reply(d, ah); - } - free(ptr); - return (-1); - } - - if (etype != ETHERTYPE_IP) { -#ifdef NET_DEBUG - if (debug) - printf("readudp: not IP. ether_type=%x\n", etype); -#endif - free(ptr); - return (-1); - } - - /* Check ip header */ - if (ip->ip_v != IPVERSION || - ip->ip_p != IPPROTO_UDP) { /* half char */ -#ifdef NET_DEBUG - if (debug) - printf("readudp: IP version or not UDP. ip_v=%d ip_p=%d\n", ip->ip_v, ip->ip_p); -#endif - free(ptr); - return (-1); - } - - hlen = ip->ip_hl << 2; - if (hlen < sizeof(*ip) || - in_cksum(ip, hlen) != 0) { -#ifdef NET_DEBUG - if (debug) - printf("readudp: short hdr or bad cksum.\n"); -#endif - free(ptr); - return (-1); - } - if (n < ntohs(ip->ip_len)) { -#ifdef NET_DEBUG - if (debug) - printf("readudp: bad length %d < %d.\n", - (int)n, ntohs(ip->ip_len)); -#endif - free(ptr); - return (-1); - } - if (d->myip.s_addr && ip->ip_dst.s_addr != d->myip.s_addr) { -#ifdef NET_DEBUG - if (debug) { - printf("readudp: bad saddr %s != ", inet_ntoa(d->myip)); - printf("%s\n", inet_ntoa(ip->ip_dst)); - } -#endif - free(ptr); - return (-1); - } - - uh = (struct udphdr *)((uintptr_t)ip + sizeof (*ip)); - /* If there were ip options, make them go away */ - if (hlen != sizeof(*ip)) { - bcopy(((u_char *)ip) + hlen, uh, uh->uh_ulen - hlen); - ip->ip_len = htons(sizeof(*ip)); - n -= hlen - sizeof(*ip); - } if (uh->uh_dport != d->myport) { #ifdef NET_DEBUG if (debug) printf("readudp: bad dport %d != %d\n", d->myport, ntohs(uh->uh_dport)); #endif free(ptr); return (-1); } #ifndef UDP_NO_CKSUM if (uh->uh_sum) { struct udpiphdr *ui; + struct ip *ip; struct ip tip; n = ntohs(uh->uh_ulen) + sizeof(*ip); - if (n > RECV_SIZE - ETHER_SIZE) { - printf("readudp: huge packet, udp len %d\n", (int)n); - free(ptr); - return (-1); - } /* Check checksum (must save and restore ip header) */ + ip = (struct ip *)uh - 1; tip = *ip; ui = (struct udpiphdr *)ip; bzero(&ui->ui_x1, sizeof(ui->ui_x1)); ui->ui_len = uh->uh_ulen; if (in_cksum(ui, n) != 0) { #ifdef NET_DEBUG if (debug) printf("readudp: bad cksum\n"); #endif free(ptr); return (-1); } *ip = tip; } #endif if (ntohs(uh->uh_ulen) < sizeof(*uh)) { #ifdef NET_DEBUG if (debug) printf("readudp: bad udp len %d < %d\n", ntohs(uh->uh_ulen), (int)sizeof(*uh)); #endif free(ptr); return (-1); } n = (n > (ntohs(uh->uh_ulen) - sizeof(*uh))) ? ntohs(uh->uh_ulen) - sizeof(*uh) : n; *pkt = ptr; *payload = (void *)((uintptr_t)uh + sizeof(*uh)); return (n); }