/*
-****************************************************************************
-* Copyright IBM Corporation 1988, 1989 - All Rights Reserved *
-* Copyright Transarc Corporation 1989 - All Rights Reserved *
-* *
-* Permission to use, copy, modify, and distribute this software and its *
-* documentation for any purpose and without fee is hereby granted, *
-* provided that the above copyright notice appear in all copies and *
-* that both that copyright notice and this permission notice appear in *
-* supporting documentation, and that the name of IBM not be used in *
-* advertising or publicity pertaining to distribution of the software *
-* without specific, written prior permission. *
-* *
-* IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL *
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL IBM *
-* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY *
-* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER *
-* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING *
-* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *
-****************************************************************************
-*/
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
#include <afsconfig.h>
#include "afs/param.h"
-RCSID("$Header$");
-#ifdef AFS_FBSD40_ENV
+#include <sys/malloc.h>
#include "rx/rx_kcommon.h"
-
#ifdef RXK_LISTENER_ENV
-int osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec,
- int nvecs, int *alength)
-{
- struct socket *asocket = (struct socket *)so;
+int
+osi_NetReceive(osi_socket asocket, struct sockaddr_in *addr,
+ struct iovec *dvec, int nvecs, int *alength)
+{
struct uio u;
int i;
struct iovec iov[RX_MAXIOVECS];
- struct sockaddr *sa;
+ struct sockaddr *sa = NULL;
int code;
int haveGlock = ISAFS_GLOCK();
- /*AFS_STATCNT(osi_NetReceive);*/
+ /*AFS_STATCNT(osi_NetReceive); */
- if (nvecs > RX_MAXIOVECS) {
- osi_Panic("osi_NetReceive: %d: Too many iovecs.\n", nvecs);
- }
+ if (nvecs > RX_MAXIOVECS)
+ osi_Panic("osi_NetReceive: %d: Too many iovecs.\n", nvecs);
- for (i = 0 ; i < nvecs ; i++) {
- iov[i].iov_base = dvec[i].iov_base;
- iov[i].iov_len = dvec[i].iov_len;
- }
+ for (i = 0; i < nvecs; i++)
+ iov[i] = dvec[i];
- u.uio_iov=&iov[0];
- u.uio_iovcnt=nvecs;
- u.uio_offset=0;
- u.uio_resid=*alength;
- u.uio_segflg=UIO_SYSSPACE;
- u.uio_rw=UIO_READ;
- u.uio_procp=NULL;
+ u.uio_iov = &iov[0];
+ u.uio_iovcnt = nvecs;
+ u.uio_offset = 0;
+ u.uio_resid = *alength;
+ u.uio_segflg = UIO_SYSSPACE;
+ u.uio_rw = UIO_READ;
+ u.uio_td = NULL;
- if (haveGlock) {
- AFS_GUNLOCK();
- }
+ if (haveGlock)
+ AFS_GUNLOCK();
code = soreceive(asocket, &sa, &u, NULL, NULL, NULL);
-#if KNET_DEBUG
+ if (haveGlock)
+ AFS_GLOCK();
+
if (code) {
- if (code == EINVAL)
- Debugger("afs NetReceive busted");
- else
- printf("y");
- }
+#if KNET_DEBUG
+ if (code == EINVAL)
+ Debugger("afs NetReceive busted");
+ else
+ printf("y");
+#else
+ return code;
#endif
- if (haveGlock) {
- AFS_GLOCK();
}
- *alength=*alength-u.uio_resid;
+ *alength -= u.uio_resid;
if (sa) {
- if (sa->sa_family == AF_INET) {
- if (addr) *addr=*(struct sockaddr_in *)sa;
- } else {
- printf("Unknown socket family %d in NetReceive\n", sa->sa_family);
- }
+ if (sa->sa_family == AF_INET) {
+ if (addr)
+ *addr = *(struct sockaddr_in *)sa;
+ } else
+ printf("Unknown socket family %d in NetReceive\n", sa->sa_family);
+ FREE(sa, M_SONAME);
}
return code;
}
extern int rxk_ListenerPid;
-void osi_StopListener(void)
+void
+osi_StopListener(void)
{
- struct proc *p;
+ struct sockaddr_in taddr;
+ struct iovec dvec;
+ struct proc *p;
+ char c;
+ c = '\0';
+
+ /*
+ * Have to drop global lock to safely do this.
+ * soclose() is currently protected by Giant,
+ * but pfind and psignal are MPSAFE.
+ */
+ int haveGlock = ISAFS_GLOCK();
+ if (haveGlock)
+ AFS_GUNLOCK();
+ soshutdown(rx_socket, SHUT_RDWR);
+ p = pfind(rxk_ListenerPid);
+ if (p) {
+ afs_warn("osi_StopListener: rxk_ListenerPid %u\n", rxk_ListenerPid);
+#if (__FreeBSD_version >= 90004)
+ kern_psignal(p, SIGUSR1);
+#else
+ psignal(p, SIGUSR1);
+#endif
+ PROC_UNLOCK(p);
+ } else
+ afs_warn("osi_StopListener: rxk_Listener not found (pid %u)\n",
+ rxk_ListenerPid);
+
+ /* Avoid destroying socket until osi_NetReceive has
+ * had a chance to clean up. Otherwise we can't restart. */
+ bzero(&taddr, sizeof(taddr));
+ taddr.sin_len = sizeof(struct sockaddr_in);
+ taddr.sin_family = AF_INET;
+ taddr.sin_port = rx_port;
+ taddr.sin_addr.s_addr = htonl(0x7f000001); /* no place like localhost */
+ bzero(&dvec, sizeof(dvec));
+ dvec.iov_base = &c;
+ dvec.iov_len = 1;
+ /* afs_osi_Sleep requires the GLOCK */
+ AFS_GLOCK();
+ while(rxk_ListenerPid) {
+ afs_warn("waiting for rxk_ListenerPid to die\n");
+ osi_NetSend(rx_socket, &taddr, &dvec, 1, 1, 0);
+ afs_osi_Sleep(&rxk_ListenerPid);
+ }
+ AFS_GUNLOCK();
+ /* in theory, we are now the only people doing anything with rx_socket */
+ soclose(rx_socket);
- soclose(rx_socket);
- p=pfind(rxk_ListenerPid);
- if (p)
- psignal(p, SIGUSR1);
+ if (haveGlock)
+ AFS_GLOCK();
}
-int
-osi_NetSend(osi_socket asocket, struct sockaddr_in *addr,
- struct iovec *dvec, int nvecs, afs_int32 alength, int istack)
+int
+osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
+ int nvecs, afs_int32 alength, int istack)
{
- register afs_int32 code;
- int s;
- int len;
+ afs_int32 code;
int i;
struct iovec iov[RX_MAXIOVECS];
- char *tdata;
struct uio u;
int haveGlock = ISAFS_GLOCK();
AFS_STATCNT(osi_NetSend);
- if (nvecs > RX_MAXIOVECS) {
- osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
- }
-
- for (i = 0 ; i < nvecs ; i++) {
- iov[i].iov_base = dvec[i].iov_base;
- iov[i].iov_len = dvec[i].iov_len;
- }
-
- u.uio_iov=&iov[0];
- u.uio_iovcnt=nvecs;
- u.uio_offset=0;
- u.uio_resid=alength;
- u.uio_segflg=UIO_SYSSPACE;
- u.uio_rw=UIO_WRITE;
- u.uio_procp=NULL;
-
- addr->sin_len=sizeof(struct sockaddr_in);
-
- if (haveGlock) {
- AFS_GUNLOCK();
- }
+ if (nvecs > RX_MAXIOVECS)
+ osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
+
+ for (i = 0; i < nvecs; i++)
+ iov[i] = dvec[i];
+
+ u.uio_iov = &iov[0];
+ u.uio_iovcnt = nvecs;
+ u.uio_offset = 0;
+ u.uio_resid = alength;
+ u.uio_segflg = UIO_SYSSPACE;
+ u.uio_rw = UIO_WRITE;
+ u.uio_td = NULL;
+
+ addr->sin_len = sizeof(struct sockaddr_in);
+
+ if (haveGlock)
+ AFS_GUNLOCK();
#if KNET_DEBUG
printf("+");
#endif
- code = sosend(asocket, addr, &u, NULL, NULL, 0, curproc);
+ code =
+ sosend(asocket, (struct sockaddr *)addr, &u, NULL, NULL, 0,
+ curthread);
#if KNET_DEBUG
if (code) {
- if (code == EINVAL)
- Debugger("afs NetSend busted");
- else
- printf("z");
+ if (code == EINVAL)
+ Debugger("afs NetSend busted");
+ else
+ printf("z");
}
#endif
- if (haveGlock) {
- AFS_GLOCK();
- }
+ if (haveGlock)
+ AFS_GLOCK();
return code;
}
#else
/* This code *almost* works :( */
static struct protosw parent_proto; /* udp proto switch */
-static void rxk_input (struct mbuf *am, int iphlen);
-static void rxk_fasttimo (void);
+static void rxk_input(struct mbuf *am, int iphlen);
+static void rxk_fasttimo(void);
/* start intercepting basic calls */
-rxk_init() {
- register struct protosw *tpro, *last;
- if (rxk_initDone) return 0;
+rxk_init()
+{
+ struct protosw *tpro, *last;
+ if (rxk_initDone)
+ return 0;
last = inetdomain.dom_protoswNPROTOSW;
for (tpro = inetdomain.dom_protosw; tpro < last; tpro++)
- if (tpro->pr_protocol == IPPROTO_UDP) {
-#if 0 /* not exported */
- /* force UDP checksumming on for AFS */
- extern int udpcksum;
- udpcksum = 1;
+ if (tpro->pr_protocol == IPPROTO_UDP) {
+#if 0 /* not exported */
+ /* force UDP checksumming on for AFS */
+ extern int udpcksum;
+ udpcksum = 1;
#endif
- memcpy(&parent_proto, tpro, sizeof(parent_proto));
- tpro->pr_input = rxk_input;
- tpro->pr_fasttimo = rxk_fasttimo;
- /*
- * don't bother with pr_drain and pr_ctlinput
- * until we have something to do
- */
- rxk_initDone = 1;
- return 0;
- }
+ memcpy(&parent_proto, tpro, sizeof(parent_proto));
+ tpro->pr_input = rxk_input;
+ tpro->pr_fasttimo = rxk_fasttimo;
+ /*
+ * don't bother with pr_drain and pr_ctlinput
+ * until we have something to do
+ */
+ rxk_initDone = 1;
+ return 0;
+ }
osi_Panic("inet:no udp");
}
-static void rxk_input (struct mbuf *am, int iphlen)
+static void
+rxk_input(struct mbuf *am, int iphlen)
{
- void (*tproc)();
- register unsigned short *tsp;
+ void (*tproc) ();
+ unsigned short *tsp;
int hdr;
struct udphdr *tu;
- register struct ip *ti;
+ struct ip *ti;
struct udpiphdr *tvu;
- register int i;
+ int i;
char *phandle;
afs_int32 code;
struct sockaddr_in taddr;
NETPRI;
/* make sure we have base ip and udp headers in first mbuf */
- if (iphlen > sizeof (struct ip)) {
- ip_stripoptions(am, NULL);
- iphlen = sizeof (struct ip);
+ if (iphlen > sizeof(struct ip)) {
+ ip_stripoptions(am, NULL);
+ iphlen = sizeof(struct ip);
}
if (am->m_len < sizeof(struct udpiphdr)) {
- am = m_pullup(am, sizeof(struct udpiphdr));
- if (!am) {
+ am = m_pullup(am, sizeof(struct udpiphdr));
+ if (!am) {
USERPRI;
return;
- }
+ }
}
ti = mtod(am, struct ip *);
/* skip basic ip hdr */
- tu = (struct udphdr *)(((char *)ti) + sizeof(struct ip));
-
+ tu = (struct udphdr *)(((char *)ti) + sizeof(struct ip));
+
/* now read the port out */
port = tu->uh_dport;
if (port) {
- for(tsp=rxk_ports, i=0; i<MAXRXPORTS;i++) {
+ for (tsp = rxk_ports, i = 0; i < MAXRXPORTS; i++) {
if (*tsp++ == port) {
/* checksum the packet */
/*
* If not enough data to reflect UDP length, drop.
*/
tvu = (struct udpiphdr *)ti;
- tlen = ntohs((u_short)tvu->ui_ulen);
+ tlen = ntohs((u_short) tvu->ui_ulen);
if ((int)ti->ip_len != tlen) {
if (tlen > (int)ti->ip_len) {
m_free(am);
m_adj(am, tlen - (int)ti->ip_len);
}
/* deliver packet to rx */
- taddr.sin_family = AF_INET; /* compute source address */
+ taddr.sin_family = AF_INET; /* compute source address */
taddr.sin_port = tu->uh_sport;
taddr.sin_addr.s_addr = ti->ip_src.s_addr;
taddr.sin_len = sizeof(taddr);
- tvu = (struct udpiphdr *) ti; /* virtual udp structure, for cksum */
+ tvu = (struct udpiphdr *)ti; /* virtual udp structure, for cksum */
/* handle the checksum. Note that this code damages the actual ip
- header (replacing it with the virtual one, which is the same size),
- so we must ensure we get everything out we need, first */
- if ( tu->uh_sum != 0) {
- /* if the checksum is there, always check it. It's crazy not
- * to, unless you can really be sure that your
- * underlying network (and interfaces and drivers and
- * DMA hardware, etc!) is error-free. First, fill
- * in entire virtual ip header. */
- memset(tvu->ui_i.ih_x1, 0, 9);
- tvu->ui_len = tvu->ui_ulen;
- tlen = ntohs((unsigned short)(tvu->ui_ulen));
- if (in_cksum(am, sizeof(struct ip) + tlen)) {
- /* checksum, including cksum field, doesn't come out 0, so
- this packet is bad */
- m_freem(am);
- USERPRI;
- return;
- }
- }
+ * header (replacing it with the virtual one, which is the same size),
+ * so we must ensure we get everything out we need, first */
+ if (tu->uh_sum != 0) {
+ /* if the checksum is there, always check it. It's crazy not
+ * to, unless you can really be sure that your
+ * underlying network (and interfaces and drivers and
+ * DMA hardware, etc!) is error-free. First, fill
+ * in entire virtual ip header. */
+ memset(tvu->ui_i.ih_x1, 0, 9);
+ tvu->ui_len = tvu->ui_ulen;
+ tlen = ntohs((unsigned short)(tvu->ui_ulen));
+ if (in_cksum(am, sizeof(struct ip) + tlen)) {
+ /* checksum, including cksum field, doesn't come out 0, so
+ * this packet is bad */
+ m_freem(am);
+ USERPRI;
+ return;
+ }
+ }
/*
* 28 is IP (20) + UDP (8) header. ulen includes
*/
data_len = ntohs(tu->uh_ulen);
data_len -= 8;
- AFS_RXGLOCK();
- if (!(*rxk_GetPacketProc)(&phandle, data_len)) {
- if (rx_mb_to_packet(am, m_freem, 28, data_len, phandle)) {
- /* XXX should just increment counter here.. */
- printf("rx: truncated UDP packet\n");
- rxi_FreePacket(phandle);
- }
- else
- (*rxk_PacketArrivalProc)(phandle, &taddr,
- rxk_portRocks[i], data_len);
- }else m_freem(am);
- AFS_RXGUNLOCK();
+ if (!(*rxk_GetPacketProc) (&phandle, data_len)) {
+ if (rx_mb_to_packet(am, m_freem, 28, data_len, phandle)) {
+ /* XXX should just increment counter here.. */
+ printf("rx: truncated UDP packet\n");
+ rxi_FreePacket(phandle);
+ } else
+ (*rxk_PacketArrivalProc) (phandle, &taddr,
+ rxk_portRocks[i], data_len);
+ } else
+ m_freem(am);
USERPRI;
return;
- }
}
}
+ }
/* if we get here, try to deliver packet to udp */
- if (tproc = parent_proto.pr_input) (*tproc)(am,iphlen);
+ if (tproc = parent_proto.pr_input)
+ (*tproc) (am, iphlen);
USERPRI;
return;
}
* Called about 5 times per second (at unknown priority?). Must go to
* splnet or obtain global lock before touching anything significant.
*/
-static void rxk_fasttimo (void)
+static void
+rxk_fasttimo(void)
{
- void (*tproc)();
+ void (*tproc) ();
struct clock temp;
/* do rx fasttimo processing here */
rxevent_RaiseEvents(&temp);
- if (tproc = parent_proto.pr_fasttimo) (*tproc)();
+ if (tproc = parent_proto.pr_fasttimo)
+ (*tproc) ();
}
/* rx_NetSend - send asize bytes at adata from asocket to host at addr.
/* set lock on sockbuf sb; can't call sblock since we're at interrupt level
* sometimes */
-static trysblock(sb)
-register struct sockbuf *sb; {
+static
+trysblock(sb)
+ struct sockbuf *sb;
+{
AFS_STATCNT(trysblock);
- if (sb->sb_flags & SB_LOCK){
- return -1; /* can't lock socket */
+ if (sb->sb_flags & SB_LOCK) {
+ return -1; /* can't lock socket */
}
sb->sb_flags |= SB_LOCK;
return 0;
/* We only have to do all the mbuf management ourselves if we can be called at
interrupt time. in RXK_LISTENER_ENV, we can just call sosend() */
-int
-osi_NetSend(osi_socket asocket, struct sockaddr_in *addr,
- struct iovec *dvec, int nvec, afs_int32 asize, int istack)
+int
+osi_NetSend(osi_socket asocket, struct sockaddr_in *addr, struct iovec *dvec,
+ int nvec, afs_int32 asize, int istack)
{
- register struct mbuf *tm, *um;
- register afs_int32 code;
+ struct mbuf *tm, *um;
+ afs_int32 code;
int s;
struct mbuf *top = 0;
- register struct mbuf *m, **mp;
+ struct mbuf *m, **mp;
int len;
char *tdata;
caddr_t tpa;
- int i,tl,rlen;
+ int i, tl, rlen;
int mlen;
int haveGlock;
#if KNET_DEBUG
- static int before=0;
+ static int before = 0;
#endif
AFS_STATCNT(osi_NetSend);
* reuse the buffers after sending, so we lost out on that trick anyway */
s = splnet();
if (trysblock(&asocket->so_snd)) {
- splx(s);
- return 1;
+ splx(s);
+ return 1;
}
mp = ⊤
i = 0;
tl = dvec[i].iov_len;
while (1) {
mlen = MLEN;
- if (top == 0) {
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (!m) {
- sbunlock(&asocket->so_snd);
- splx(s);
- return 1;
- }
- mlen = MHLEN;
- m->m_pkthdr.len = 0;
- m->m_pkthdr.rcvif = NULL;
- } else
- MGET(m, M_DONTWAIT, MT_DATA);
+ if (top == 0) {
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (!m) {
+ sbunlock(&asocket->so_snd);
+ splx(s);
+ return 1;
+ }
+ mlen = MHLEN;
+ m->m_pkthdr.len = 0;
+ m->m_pkthdr.rcvif = NULL;
+ } else
+ MGET(m, M_DONTWAIT, MT_DATA);
if (!m) {
/* can't get an mbuf, give up */
- if (top) m_freem(top); /* free mbuf list we're building */
- sbunlock(&asocket->so_snd);
+ if (top)
+ m_freem(top); /* free mbuf list we're building */
+ sbunlock(&asocket->so_snd);
splx(s);
return 1;
}
*/
if (asize >= 4 * MLEN) { /* try to get cluster mbuf */
/* different algorithms for getting cluster mbuf */
- MCLGET(m, M_DONTWAIT);
- if ((m->m_flags & M_EXT) == 0)
- goto nopages;
- mlen = MCLBYTES;
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0)
+ goto nopages;
+ mlen = MCLBYTES;
/* now compute usable size */
- len = MIN(mlen, asize);
+ len = MIN(mlen, asize);
/* Should I look at MAPPED_MBUFS??? */
} else {
-nopages:
- len = MIN(mlen, asize);
+ nopages:
+ len = MIN(mlen, asize);
}
m->m_len = 0;
- *mp = m; /* XXXX */
- top->m_pkthdr.len += len;
+ *mp = m; /* XXXX */
+ top->m_pkthdr.len += len;
tpa = mtod(m, caddr_t);
while (len) {
- rlen = MIN(len, tl);
- memcpy(tpa, tdata, rlen);
- asize -= rlen;
- len -= rlen;
- tpa += rlen;
- m->m_len += rlen;
- tdata += rlen;
- tl -= rlen;
- if (tl <= 0) {
- i++;
- if (i > nvec) {
- /* shouldn't come here! */
- asize = 0; /* so we make progress toward completion */
- break;
+ rlen = MIN(len, tl);
+ memcpy(tpa, tdata, rlen);
+ asize -= rlen;
+ len -= rlen;
+ tpa += rlen;
+ m->m_len += rlen;
+ tdata += rlen;
+ tl -= rlen;
+ if (tl <= 0) {
+ i++;
+ if (i > nvec) {
+ /* shouldn't come here! */
+ asize = 0; /* so we make progress toward completion */
+ break;
+ }
+ tdata = dvec[i].iov_base;
+ tl = dvec[i].iov_len;
}
- tdata = dvec[i].iov_base;
- tl = dvec[i].iov_len;
- }
}
*mp = m;
mp = &m->m_next;
if (asize <= 0)
- break;
+ break;
}
tm = top;
/* setup mbuf corresponding to destination address */
um = m_get(M_DONTWAIT, MT_SONAME);
if (!um) {
- if (top) m_freem(top); /* free mbuf chain */
- sbunlock(&asocket->so_snd);
+ if (top)
+ m_freem(top); /* free mbuf chain */
+ sbunlock(&asocket->so_snd);
splx(s);
return 1;
}
/* note that udp_usrreq frees funny mbuf. We hold onto data, but mbuf
* around it is gone. */
/* haveGlock = ISAFS_GLOCK();
- if (haveGlock) {
- AFS_GUNLOCK();
- } */
+ * if (haveGlock) {
+ * AFS_GUNLOCK();
+ * } */
/* SOCKET_LOCK(asocket); */
/* code = (*asocket->so_proto->pr_usrreq)(asocket, PRU_SEND, tm, um, 0); */
#if KNET_DEBUG
- if (before) Debugger("afs NetSend before");
+ if (before)
+ Debugger("afs NetSend before");
#endif
- code = (*asocket->so_proto->pr_usrreqs->pru_send)(asocket, 0, tm,
- (struct sockaddr *) addr,
- um, &proc0);
+ code =
+ (*asocket->so_proto->pr_usrreqs->pru_send) (asocket, 0, tm,
+ (struct sockaddr *)
+ addr, um, &proc0);
/* SOCKET_UNLOCK(asocket); */
/* if (haveGlock) {
- AFS_GLOCK();
- } */
+ * AFS_GLOCK();
+ * } */
sbunlock(&asocket->so_snd);
splx(s);
#if KNET_DEBUG
if (code) {
- if (code == EINVAL)
- Debugger("afs NetSend busted");
- else
- printf("z");
+ if (code == EINVAL)
+ Debugger("afs NetSend busted");
+ else
+ printf("z");
}
#endif
return code;
}
#endif
-
-#endif /* AFS_FBSD40_ENV */