rx-allow-jumbogram-disabling-really-20080822
[openafs.git] / src / rx / rx_kcommon.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * rx_kcommon.c - Common kernel RX code for all system types.
12  */
13
14 #include <afsconfig.h>
15 #include "afs/param.h"
16
17 RCSID
18     ("$Header$");
19
20 #include "rx/rx_kcommon.h"
21
22 #ifdef AFS_HPUX110_ENV
23 #include "h/tihdr.h"
24 #include <xti.h>
25 #endif
26 #include "afsint.h"
27
28 #ifndef RXK_LISTENER_ENV
29 int (*rxk_PacketArrivalProc) (struct rx_packet * ahandle, struct sockaddr_in * afrom, struct socket *arock, afs_int32 asize);   /* set to packet allocation procedure */
30 int (*rxk_GetPacketProc) (struct rx_packet **ahandle, int asize);
31 #endif
32
33 osi_socket *rxk_NewSocketHost(afs_uint32 ahost, short aport);
34 extern struct interfaceAddr afs_cb_interface;
35
36 rxk_ports_t rxk_ports;
37 rxk_portRocks_t rxk_portRocks;
38
39 int rxk_initDone = 0;
40
41 #if !defined(AFS_SUN5_ENV) && !defined(AFS_SGI62_ENV)
42 #define ADDRSPERSITE 16
43 static afs_uint32 myNetAddrs[ADDRSPERSITE];
44 static int myNetMTUs[ADDRSPERSITE];
45 static int numMyNetAddrs = 0;
46 #endif
47
48 #if defined(AFS_DARWIN80_ENV)
49 #define sobind sock_bind
50 #define soclose sock_close
51 #endif
52
53 /* add a port to the monitored list, port # is in network order */
54 static int
55 rxk_AddPort(u_short aport, char *arock)
56 {
57     int i;
58     unsigned short *tsp, ts;
59     int zslot;
60
61     zslot = -1;                 /* look for an empty slot simultaneously */
62     for (i = 0, tsp = rxk_ports; i < MAXRXPORTS; i++, tsp++) {
63         if (((ts = *tsp) == 0) && (zslot == -1))
64             zslot = i;
65         if (ts == aport) {
66             return 0;
67         }
68     }
69     /* otherwise allocate a new port slot */
70     if (zslot < 0)
71         return E2BIG;           /* all full */
72     rxk_ports[zslot] = aport;
73     rxk_portRocks[zslot] = arock;
74     return 0;
75 }
76
77 /* remove as port from the monitored list, port # is in network order */
78 int
79 rxk_DelPort(u_short aport)
80 {
81     register int i;
82     register unsigned short *tsp;
83
84     for (i = 0, tsp = rxk_ports; i < MAXRXPORTS; i++, tsp++) {
85         if (*tsp == aport) {
86             /* found it, adjust ref count and free the port reference if all gone */
87             *tsp = 0;
88             return 0;
89         }
90     }
91     /* otherwise port not found */
92     return ENOENT;
93 }
94
95 void
96 rxk_shutdownPorts(void)
97 {
98     int i;
99     for (i = 0; i < MAXRXPORTS; i++) {
100         if (rxk_ports[i]) {
101             rxk_ports[i] = 0;
102 #if ! defined(AFS_SUN5_ENV) && ! defined(UKERNEL) && ! defined(RXK_LISTENER_ENV)
103             soclose((struct socket *)rxk_portRocks[i]);
104 #endif
105             rxk_portRocks[i] = NULL;
106         }
107     }
108 }
109
110 osi_socket
111 rxi_GetHostUDPSocket(u_int host, u_short port)
112 {
113     osi_socket *sockp;
114     sockp = (osi_socket *)rxk_NewSocketHost(host, port);
115     if (sockp == (osi_socket *)0)
116         return OSI_NULLSOCKET;
117     rxk_AddPort(port, (char *)sockp);
118     return (osi_socket) sockp;
119 }
120
121 osi_socket
122 rxi_GetUDPSocket(u_short port)
123 {
124     return rxi_GetHostUDPSocket(htonl(INADDR_ANY), port);
125 }
126
127 #if !defined(AFS_LINUX26_ENV)
128 void
129 osi_Panic(msg, a1, a2, a3)
130      char *msg;
131 {
132     if (!msg)
133         msg = "Unknown AFS panic";
134
135     printf(msg, a1, a2, a3);
136 #ifdef AFS_LINUX20_ENV
137     * ((char *) 0) = 0; 
138 #else
139     panic(msg);
140 #endif
141 }
142
143 /*
144  * osi_utoa() - write the NUL-terminated ASCII decimal form of the given
145  * unsigned long value into the given buffer.  Returns 0 on success,
146  * and a value less than 0 on failure.  The contents of the buffer is
147  * defined only on success.
148  */
149
150 int
151 osi_utoa(char *buf, size_t len, unsigned long val)
152 {
153     long k;                     /* index of first byte of string value */
154
155     /* we definitely need room for at least one digit and NUL */
156
157     if (len < 2) {
158         return -1;
159     }
160
161     /* compute the string form from the high end of the buffer */
162
163     buf[len - 1] = '\0';
164     for (k = len - 2; k >= 0; k--) {
165         buf[k] = val % 10 + '0';
166         val /= 10;
167
168         if (val == 0)
169             break;
170     }
171
172     /* did we finish converting val to string form? */
173
174     if (val != 0) {
175         return -2;
176     }
177
178     /* this should never happen */
179
180     if (k < 0) {
181         return -3;
182     }
183
184     /* this should never happen */
185
186     if (k >= len) {
187         return -4;
188     }
189
190     /* if necessary, relocate string to beginning of buf[] */
191
192     if (k > 0) {
193
194         /*
195          * We need to achieve the effect of calling
196          *
197          * memmove(buf, &buf[k], len - k);
198          *
199          * However, since memmove() is not available in all
200          * kernels, we explicitly do an appropriate copy.
201          */
202
203         char *dst = buf;
204         char *src = buf + k;
205
206         while ((*dst++ = *src++) != '\0')
207             continue;
208     }
209
210     return 0;
211 }
212
213 /*
214  * osi_AssertFailK() -- used by the osi_Assert() macro.
215  *
216  * It essentially does
217  *
218  * osi_Panic("assertion failed: %s, file: %s, line: %d", expr, file, line);
219  *
220  * Since the kernel version of osi_Panic() only passes its first
221  * argument to the native panic(), we construct a single string and hand
222  * that to osi_Panic().
223  */
224 void
225 osi_AssertFailK(const char *expr, const char *file, int line)
226 {
227     static const char msg0[] = "assertion failed: ";
228     static const char msg1[] = ", file: ";
229     static const char msg2[] = ", line: ";
230     static const char msg3[] = "\n";
231
232     /*
233      * These buffers add up to 1K, which is a pleasantly nice round
234      * value, but probably not vital.
235      */
236     char buf[1008];
237     char linebuf[16];
238
239     /* check line number conversion */
240
241     if (osi_utoa(linebuf, sizeof linebuf, line) < 0) {
242         osi_Panic("osi_AssertFailK: error in osi_utoa()\n");
243     }
244
245     /* okay, panic */
246
247 #define ADDBUF(BUF, STR)                                        \
248         if (strlen(BUF) + strlen((char *)(STR)) + 1 <= sizeof BUF) {    \
249                 strcat(BUF, (char *)(STR));                             \
250         }
251
252     buf[0] = '\0';
253     ADDBUF(buf, msg0);
254     ADDBUF(buf, expr);
255     ADDBUF(buf, msg1);
256     ADDBUF(buf, file);
257     ADDBUF(buf, msg2);
258     ADDBUF(buf, linebuf);
259     ADDBUF(buf, msg3);
260
261 #undef ADDBUF
262
263     osi_Panic(buf);
264 }
265 #else
266 void
267 osi_AssertFailK(const char *expr, const char *file, int line)
268 {
269     printk(KERN_CRIT "assertion failed: %s, file: %s, line: %d\n", expr, file, line);
270 }
271 #endif
272
273 #ifndef UKERNEL
274 /* This is the server process request loop. Kernel server
275  * processes never become listener threads */
276 void *
277 rx_ServerProc(void *unused)
278 {
279     int threadID;
280
281     rxi_MorePackets(rx_maxReceiveWindow + 2);   /* alloc more packets */
282     rxi_dataQuota += rx_initSendWindow; /* Reserve some pkts for hard times */
283     /* threadID is used for making decisions in GetCall.  Get it by bumping
284      * number of threads handling incoming calls */
285     threadID = rxi_availProcs++;
286
287 #ifdef RX_ENABLE_LOCKS
288     AFS_GUNLOCK();
289 #endif /* RX_ENABLE_LOCKS */
290     rxi_ServerProc(threadID, NULL, NULL);
291 #ifdef RX_ENABLE_LOCKS
292     AFS_GLOCK();
293 #endif /* RX_ENABLE_LOCKS */
294
295     return NULL;
296 }
297 #endif /* !UKERNEL */
298
299 #ifndef RXK_LISTENER_ENV
300 /* asize includes the Rx header */
301 static int
302 MyPacketProc(struct rx_packet **ahandle, int asize)
303 {
304     struct rx_packet *tp;
305
306     /* If this is larger than we expected, increase rx_maxReceiveDataSize */
307     /* If we can't scrounge enough cbufs, then we have to drop the packet,
308      * but we should set a flag so we magic up some more at our leisure.
309      */
310
311     if ((asize >= 0) && (asize <= RX_MAX_PACKET_SIZE)) {
312         tp = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE);
313         if (tp && (tp->length + RX_HEADER_SIZE) < asize) {
314             if (0 <
315                 rxi_AllocDataBuf(tp, asize - (tp->length + RX_HEADER_SIZE),
316                                  RX_PACKET_CLASS_RECV_CBUF)) {
317                 rxi_FreePacket(tp);
318                 tp = NULL;
319                 MUTEX_ENTER(&rx_stats_mutex);
320                 rx_stats.noPacketBuffersOnRead++;
321                 MUTEX_EXIT(&rx_stats_mutex);
322             }
323         }
324     } else {
325         /*
326          * XXX if packet is too long for our buffer,
327          * should do this at a higher layer and let other
328          * end know we're losing.
329          */
330         MUTEX_ENTER(&rx_stats_mutex);
331         rx_stats.bogusPacketOnRead++;
332         MUTEX_EXIT(&rx_stats_mutex);
333         /* I DON"T LIKE THIS PRINTF -- PRINTFS MAKE THINGS VERY VERY SLOOWWW */
334         dpf(("rx: packet dropped: bad ulen=%d\n", asize));
335         tp = NULL;
336     }
337
338     if (!tp)
339         return -1;
340     /* otherwise we have a packet, set appropriate values */
341     *ahandle = tp;
342     return 0;
343 }
344
345 static int
346 MyArrivalProc(struct rx_packet *ahandle,
347               struct sockaddr_in *afrom,
348               struct socket *arock,
349               afs_int32 asize)
350 {
351     /* handle basic rx packet */
352     ahandle->length = asize - RX_HEADER_SIZE;
353     rxi_DecodePacketHeader(ahandle);
354     ahandle =
355         rxi_ReceivePacket(ahandle, arock,
356                           afrom->sin_addr.s_addr, afrom->sin_port, NULL,
357                           NULL);
358
359     /* free the packet if it has been returned */
360     if (ahandle)
361         rxi_FreePacket(ahandle);
362     return 0;
363 }
364 #endif /* !RXK_LISTENER_ENV */
365
366 void
367 rxi_StartListener(void)
368 {
369     /* if kernel, give name of appropriate procedures */
370 #ifndef RXK_LISTENER_ENV
371     rxk_GetPacketProc = MyPacketProc;
372     rxk_PacketArrivalProc = MyArrivalProc;
373     rxk_init();
374 #endif
375 }
376
377 /* Called from rxi_FindPeer, when initializing a clear rx_peer structure,
378   to get interesting information. */
379 void
380 rxi_InitPeerParams(register struct rx_peer *pp)
381 {
382     u_short rxmtu;
383     afs_int32 i, mtu;
384
385 #ifdef  ADAPT_MTU
386 #ifndef AFS_SUN5_ENV
387 #ifdef AFS_USERSPACE_IP_ADDR
388     i = rxi_Findcbi(pp->host);
389     if (i == -1) {
390         pp->timeout.sec = 3;
391         /* pp->timeout.usec = 0; */
392         pp->ifMTU = RX_REMOTE_PACKET_SIZE;
393     } else {
394         pp->timeout.sec = 2;
395         /* pp->timeout.usec = 0; */
396         pp->ifMTU = MIN(RX_MAX_PACKET_SIZE, rx_MyMaxSendSize);
397     }
398     if (i != -1) {
399         mtu = ntohl(afs_cb_interface.mtu[i]);
400         /* Diminish the packet size to one based on the MTU given by
401          * the interface. */
402         if (mtu > (RX_IPUDP_SIZE + RX_HEADER_SIZE)) {
403             rxmtu = mtu - RX_IPUDP_SIZE;
404             if (rxmtu < pp->ifMTU)
405                 pp->ifMTU = rxmtu;
406         }
407     } else {                    /* couldn't find the interface, so assume the worst */
408         pp->ifMTU = RX_REMOTE_PACKET_SIZE;
409     }
410 #else /* AFS_USERSPACE_IP_ADDR */
411     AFS_IFNET_T ifn;
412
413 #if !defined(AFS_SGI62_ENV)
414     if (numMyNetAddrs == 0)
415         (void)rxi_GetIFInfo();
416 #endif
417
418     ifn = rxi_FindIfnet(pp->host, NULL);
419     if (ifn) {
420         pp->timeout.sec = 2;
421         /* pp->timeout.usec = 0; */
422         pp->ifMTU = MIN(RX_MAX_PACKET_SIZE, rx_MyMaxSendSize);
423 #ifdef IFF_POINTOPOINT
424         if (ifnet_flags(ifn) & IFF_POINTOPOINT) {
425             /* wish we knew the bit rate and the chunk size, sigh. */
426             pp->timeout.sec = 4;
427             pp->ifMTU = RX_PP_PACKET_SIZE;
428         }
429 #endif /* IFF_POINTOPOINT */
430         /* Diminish the packet size to one based on the MTU given by
431          * the interface. */
432         if (ifnet_mtu(ifn) > (RX_IPUDP_SIZE + RX_HEADER_SIZE)) {
433             rxmtu = ifnet_mtu(ifn) - RX_IPUDP_SIZE;
434             if (rxmtu < pp->ifMTU)
435                 pp->ifMTU = rxmtu;
436         }
437     } else {                    /* couldn't find the interface, so assume the worst */
438         pp->timeout.sec = 3;
439         /* pp->timeout.usec = 0; */
440         pp->ifMTU = RX_REMOTE_PACKET_SIZE;
441     }
442 #endif /* else AFS_USERSPACE_IP_ADDR */
443 #else /* AFS_SUN5_ENV */
444     mtu = rxi_FindIfMTU(pp->host);
445
446     if (mtu <= 0) {
447         pp->timeout.sec = 3;
448         /* pp->timeout.usec = 0; */
449         pp->ifMTU = RX_REMOTE_PACKET_SIZE;
450     } else {
451         pp->timeout.sec = 2;
452         /* pp->timeout.usec = 0; */
453         pp->ifMTU = MIN(RX_MAX_PACKET_SIZE, rx_MyMaxSendSize);
454     }
455
456     if (mtu > 0) {
457         /* Diminish the packet size to one based on the MTU given by
458          * the interface. */
459         if (mtu > (RX_IPUDP_SIZE + RX_HEADER_SIZE)) {
460             rxmtu = mtu - RX_IPUDP_SIZE;
461             if (rxmtu < pp->ifMTU)
462                 pp->ifMTU = rxmtu;
463         }
464     } else {                    /* couldn't find the interface, so assume the worst */
465         pp->ifMTU = RX_REMOTE_PACKET_SIZE;
466     }
467 #endif /* AFS_SUN5_ENV */
468 #else /* ADAPT_MTU */
469     pp->rateFlag = 2;           /* start timing after two full packets */
470     pp->timeout.sec = 2;
471     pp->ifMTU = OLD_MAX_PACKET_SIZE;
472 #endif /* else ADAPT_MTU */
473     pp->ifMTU = rxi_AdjustIfMTU(pp->ifMTU);
474     pp->maxMTU = OLD_MAX_PACKET_SIZE;   /* for compatibility with old guys */
475     pp->natMTU = MIN(pp->ifMTU, OLD_MAX_PACKET_SIZE);
476     pp->ifDgramPackets =
477         MIN(rxi_nDgramPackets,
478             rxi_AdjustDgramPackets(rxi_nSendFrags, pp->ifMTU));
479     pp->maxDgramPackets = 1;
480
481     /* Initialize slow start parameters */
482     pp->MTU = MIN(pp->natMTU, pp->maxMTU);
483     pp->cwind = 1;
484     pp->nDgramPackets = 1;
485     pp->congestSeq = 0;
486 }
487
488
489 /* The following code is common to several system types, but not all. The
490  * separate ones are found in the system specific subdirectories.
491  */
492
493
494 #if ! defined(AFS_AIX_ENV) && ! defined(AFS_SUN5_ENV) && ! defined(UKERNEL) && ! defined(AFS_LINUX20_ENV) && !defined (AFS_DARWIN_ENV) && !defined (AFS_XBSD_ENV)
495 /* Routine called during the afsd "-shutdown" process to put things back to
496  * the initial state.
497  */
498 static struct protosw parent_proto;     /* udp proto switch */
499
500 void
501 shutdown_rxkernel(void)
502 {
503     register struct protosw *tpro, *last;
504     last = inetdomain.dom_protoswNPROTOSW;
505     for (tpro = inetdomain.dom_protosw; tpro < last; tpro++)
506         if (tpro->pr_protocol == IPPROTO_UDP) {
507             /* restore original udp protocol switch */
508             memcpy((void *)tpro, (void *)&parent_proto, sizeof(parent_proto));
509             memset((void *)&parent_proto, 0, sizeof(parent_proto));
510             rxk_initDone = 0;
511             rxk_shutdownPorts();
512             return;
513         }
514     dpf(("shutdown_rxkernel: no udp proto"));
515 }
516 #endif /* !AIX && !SUN && !NCR  && !UKERNEL */
517
518 #if !defined(AFS_SUN5_ENV) && !defined(AFS_SGI62_ENV)
519 /* Determine what the network interfaces are for this machine. */
520
521 #ifdef AFS_USERSPACE_IP_ADDR
522 int
523 rxi_GetcbiInfo(void)
524 {
525     int i, j, different = 0, num = ADDRSPERSITE;
526     int rxmtu, maxmtu;
527     afs_uint32 ifinaddr;
528     afs_uint32 addrs[ADDRSPERSITE];
529     int mtus[ADDRSPERSITE];
530
531     memset((void *)addrs, 0, sizeof(addrs));
532     memset((void *)mtus, 0, sizeof(mtus));
533
534     if (afs_cb_interface.numberOfInterfaces < num)
535         num = afs_cb_interface.numberOfInterfaces;
536     for (i = 0; i < num; i++) {
537         if (!afs_cb_interface.mtu[i])
538             afs_cb_interface.mtu[i] = htonl(1500);
539         rxmtu = (ntohl(afs_cb_interface.mtu[i]) - RX_IPUDP_SIZE);
540         ifinaddr = ntohl(afs_cb_interface.addr_in[i]);
541         if (myNetAddrs[i] != ifinaddr)
542             different++;
543
544         mtus[i] = rxmtu;
545         rxmtu = rxi_AdjustIfMTU(rxmtu);
546         maxmtu =
547             rxmtu * rxi_nRecvFrags + ((rxi_nRecvFrags - 1) * UDP_HDR_SIZE);
548         maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
549         addrs[i++] = ifinaddr;
550         if ((ifinaddr != 0x7f000001) && (maxmtu > rx_maxReceiveSize)) {
551             rx_maxReceiveSize = MIN(RX_MAX_PACKET_SIZE, maxmtu);
552             rx_maxReceiveSize = MIN(rx_maxReceiveSize, rx_maxReceiveSizeUser);
553         }
554     }
555
556     rx_maxJumboRecvSize =
557         RX_HEADER_SIZE + (rxi_nDgramPackets * RX_JUMBOBUFFERSIZE) +
558         ((rxi_nDgramPackets - 1) * RX_JUMBOHEADERSIZE);
559     rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
560
561     if (different) {
562         for (j = 0; j < i; j++) {
563             myNetMTUs[j] = mtus[j];
564             myNetAddrs[j] = addrs[j];
565         }
566     }
567     return different;
568 }
569
570
571 /* Returns the afs_cb_interface inxex which best matches address.
572  * If none is found, we return -1.
573  */
574 afs_int32
575 rxi_Findcbi(afs_uint32 addr)
576 {
577     int j;
578     afs_uint32 myAddr, thisAddr, netMask, subnetMask;
579     afs_int32 rvalue = -1;
580     int match_value = 0;
581
582     if (numMyNetAddrs == 0)
583         (void)rxi_GetcbiInfo();
584
585     myAddr = ntohl(addr);
586
587     if (IN_CLASSA(myAddr))
588         netMask = IN_CLASSA_NET;
589     else if (IN_CLASSB(myAddr))
590         netMask = IN_CLASSB_NET;
591     else if (IN_CLASSC(myAddr))
592         netMask = IN_CLASSC_NET;
593     else
594         netMask = 0;
595
596     for (j = 0; j < afs_cb_interface.numberOfInterfaces; j++) {
597         thisAddr = ntohl(afs_cb_interface.addr_in[j]);
598         subnetMask = ntohl(afs_cb_interface.subnetmask[j]);
599         if ((myAddr & netMask) == (thisAddr & netMask)) {
600             if ((myAddr & subnetMask) == (thisAddr & subnetMask)) {
601                 if (myAddr == thisAddr) {
602                     match_value = 4;
603                     rvalue = j;
604                     break;
605                 }
606                 if (match_value < 3) {
607                     match_value = 3;
608                     rvalue = j;
609                 }
610             } else {
611                 if (match_value < 2) {
612                     match_value = 2;
613                     rvalue = j;
614                 }
615             }
616         }
617     }
618
619     return (rvalue);
620 }
621
622 #else /* AFS_USERSPACE_IP_ADDR */
623
624 #if !defined(AFS_AIX41_ENV) && !defined(AFS_DUX40_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
625 #define IFADDR2SA(f) (&((f)->ifa_addr))
626 #else /* AFS_AIX41_ENV */
627 #define IFADDR2SA(f) ((f)->ifa_addr)
628 #endif
629
630 int
631 rxi_GetIFInfo(void)
632 {
633     int i = 0;
634     int different = 0;
635
636     register int rxmtu, maxmtu;
637     afs_uint32 addrs[ADDRSPERSITE];
638     int mtus[ADDRSPERSITE];
639     afs_uint32 ifinaddr;
640 #if defined(AFS_DARWIN80_ENV)
641     errno_t t;
642     unsigned int count;
643     int cnt=0, m, j;
644     ifaddr_t *ifads;
645     ifnet_t *ifn;
646     struct sockaddr sout;
647     struct sockaddr_in *sin;
648     struct in_addr pin;
649 #else
650     struct ifaddr *ifad;        /* ifnet points to a if_addrlist of ifaddrs */
651     register struct ifnet *ifn;
652 #endif
653
654     memset(addrs, 0, sizeof(addrs));
655     memset(mtus, 0, sizeof(mtus));
656
657 #if defined(AFS_DARWIN80_ENV)
658     if (!ifnet_list_get(AF_INET, &ifn, &count)) {
659         for (m = 0; m < count; m++) {
660             if (!ifnet_get_address_list(ifn[m], &ifads)) {
661                 for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
662                     if ((t = ifaddr_address(ifads[j], &sout, sizeof(struct sockaddr))) == 0) {
663                         sin = (struct sockaddr_in *)&sout;
664                         rxmtu = ifnet_mtu(ifaddr_ifnet(ifads[j])) - RX_IPUDP_SIZE;
665                         ifinaddr = ntohl(sin->sin_addr.s_addr);
666                         if (myNetAddrs[i] != ifinaddr) {
667                             different++;
668                         }
669                         mtus[i] = rxmtu;
670                         rxmtu = rxi_AdjustIfMTU(rxmtu);
671                         maxmtu =
672                             rxmtu * rxi_nRecvFrags +
673                             ((rxi_nRecvFrags - 1) * UDP_HDR_SIZE);
674                         maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
675                         addrs[i++] = ifinaddr;
676                         if ((ifinaddr != 0x7f000001) && 
677                             (maxmtu > rx_maxReceiveSize)) {
678                             rx_maxReceiveSize = 
679                                 MIN(RX_MAX_PACKET_SIZE, maxmtu);
680                             rx_maxReceiveSize =
681                                 MIN(rx_maxReceiveSize, rx_maxReceiveSizeUser);
682                         }
683                         cnt++;
684                     }
685                 }
686                 ifnet_free_address_list(ifads);
687             }
688         }
689         ifnet_list_free(ifn);
690     }
691 #else
692 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
693     TAILQ_FOREACH(ifn, &ifnet, if_link) {
694         if (i >= ADDRSPERSITE)
695             break;
696 #elif defined(AFS_OBSD_ENV)
697     for (ifn = ifnet.tqh_first; i < ADDRSPERSITE && ifn != NULL;
698          ifn = ifn->if_list.tqe_next) {
699 #else
700     for (ifn = ifnet; ifn != NULL && i < ADDRSPERSITE; ifn = ifn->if_next) {
701 #endif
702         rxmtu = (ifn->if_mtu - RX_IPUDP_SIZE);
703 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
704         TAILQ_FOREACH(ifad, &ifn->if_addrhead, ifa_link) {
705             if (i >= ADDRSPERSITE)
706                 break;
707 #elif defined(AFS_OBSD_ENV)
708         for (ifad = ifn->if_addrlist.tqh_first;
709              ifad != NULL && i < ADDRSPERSITE;
710              ifad = ifad->ifa_list.tqe_next) {
711 #else
712         for (ifad = ifn->if_addrlist; ifad != NULL && i < ADDRSPERSITE;
713              ifad = ifad->ifa_next) {
714 #endif
715             if (IFADDR2SA(ifad)->sa_family == AF_INET) {
716                 ifinaddr =
717                     ntohl(((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
718                           s_addr);
719                 if (myNetAddrs[i] != ifinaddr) {
720                     different++;
721                 }
722                 mtus[i] = rxmtu;
723                 rxmtu = rxi_AdjustIfMTU(rxmtu);
724                 maxmtu =
725                     rxmtu * rxi_nRecvFrags +
726                     ((rxi_nRecvFrags - 1) * UDP_HDR_SIZE);
727                 maxmtu = rxi_AdjustMaxMTU(rxmtu, maxmtu);
728                 addrs[i++] = ifinaddr;
729                 if ((ifinaddr != 0x7f000001) && (maxmtu > rx_maxReceiveSize)) {
730                     rx_maxReceiveSize = MIN(RX_MAX_PACKET_SIZE, maxmtu);
731                     rx_maxReceiveSize =
732                         MIN(rx_maxReceiveSize, rx_maxReceiveSizeUser);
733                 }
734             }
735         }
736     }
737 #endif
738
739     rx_maxJumboRecvSize =
740         RX_HEADER_SIZE + rxi_nDgramPackets * RX_JUMBOBUFFERSIZE +
741         (rxi_nDgramPackets - 1) * RX_JUMBOHEADERSIZE;
742     rx_maxJumboRecvSize = MAX(rx_maxJumboRecvSize, rx_maxReceiveSize);
743
744     if (different) {
745         int l;
746         for (l = 0; l < i; l++) {
747             myNetMTUs[l] = mtus[l];
748             myNetAddrs[l] = addrs[l];
749         }
750     }
751     return different;
752 }
753
754 #if defined(AFS_DARWIN60_ENV) || defined(AFS_XBSD_ENV)
755 /* Returns ifnet which best matches address */
756 #ifdef AFS_DARWIN80_ENV
757 ifnet_t
758 #else
759 struct ifnet *
760 #endif
761 rxi_FindIfnet(afs_uint32 addr, afs_uint32 * maskp)
762 {
763     struct sockaddr_in s, sr;
764 #ifdef AFS_DARWIN80_ENV
765     ifaddr_t ifad;
766 #else
767     struct ifaddr *ifad;
768 #endif
769
770     s.sin_family = AF_INET;
771     s.sin_addr.s_addr = addr;
772 #ifdef AFS_DARWIN80_ENV
773     ifad = ifaddr_withnet((struct sockaddr *)&s);
774 #else
775     ifad = ifa_ifwithnet((struct sockaddr *)&s);
776 #endif
777
778 #ifdef AFS_DARWIN80_ENV
779     if (ifad && maskp) {
780         ifaddr_netmask(ifad, (struct sockaddr *)&sr, sizeof(sr));
781         *maskp = sr.sin_addr.s_addr;
782     }
783     return (ifad ? ifaddr_ifnet(ifad) : NULL);
784 #else
785     if (ifad && maskp)
786         *maskp = ((struct sockaddr_in *)ifad->ifa_netmask)->sin_addr.s_addr;
787     return (ifad ? ifad->ifa_ifp : NULL);
788 #endif
789 }
790
791 #else /* DARWIN60 || XBSD */
792
793 /* Returns ifnet which best matches address */
794 struct ifnet *
795 rxi_FindIfnet(afs_uint32 addr, afs_uint32 * maskp)
796 {
797     int match_value = 0;
798     extern struct in_ifaddr *in_ifaddr;
799     struct in_ifaddr *ifa, *ifad = NULL;
800
801     addr = ntohl(addr);
802
803 #if defined(AFS_DARWIN_ENV)
804     for (ifa = TAILQ_FIRST(&in_ifaddrhead); ifa;
805          ifa = TAILQ_NEXT(ifa, ia_link)) {
806 #else
807     for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
808 #endif
809         if ((addr & ifa->ia_netmask) == ifa->ia_net) {
810             if ((addr & ifa->ia_subnetmask) == ifa->ia_subnet) {
811                 if (IA_SIN(ifa)->sin_addr.s_addr == addr) {     /* ie, ME!!!  */
812                     match_value = 4;
813                     ifad = ifa;
814                     goto done;
815                 }
816                 if (match_value < 3) {
817                     ifad = ifa;
818                     match_value = 3;
819                 }
820             } else {
821                 if (match_value < 2) {
822                     ifad = ifa;
823                     match_value = 2;
824                 }
825             }
826         }                       /* if net matches */
827     }                           /* for all in_ifaddrs */
828
829   done:
830     if (ifad && maskp)
831         *maskp = ifad->ia_subnetmask;
832     return (ifad ? ifad->ia_ifp : NULL);
833 }
834 #endif /* else DARWIN60 || XBSD */
835 #endif /* else AFS_USERSPACE_IP_ADDR */
836 #endif /* !SUN5 && !SGI62 */
837
838
839 /* rxk_NewSocket, rxk_FreeSocket and osi_NetSend are from the now defunct
840  * afs_osinet.c. One could argue that rxi_NewSocket could go into the
841  * system specific subdirectories for all systems. But for the moment,
842  * most of it is simple to follow common code.
843  */
844 #if !defined(UKERNEL)
845 #if !defined(AFS_SUN5_ENV) && !defined(AFS_LINUX20_ENV)
846 /* rxk_NewSocket creates a new socket on the specified port. The port is
847  * in network byte order.
848  */
849 osi_socket *
850 rxk_NewSocketHost(afs_uint32 ahost, short aport)
851 {
852     register afs_int32 code;
853 #ifdef AFS_DARWIN80_ENV
854     socket_t newSocket;
855 #else
856     struct socket *newSocket;
857 #endif
858 #if (!defined(AFS_HPUX1122_ENV) && !defined(AFS_FBSD50_ENV))
859     struct mbuf *nam;
860 #endif
861     struct sockaddr_in myaddr;
862 #ifdef AFS_HPUX110_ENV
863     /* prototype copied from kernel source file streams/str_proto.h */
864     extern MBLKP allocb_wait(int, int);
865     MBLKP bindnam;
866     int addrsize = sizeof(struct sockaddr_in);
867     struct file *fp;
868     extern struct fileops socketops;
869 #endif
870 #ifdef AFS_SGI65_ENV
871     bhv_desc_t bhv;
872 #endif
873
874     AFS_STATCNT(osi_NewSocket);
875 #if (defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)) && defined(KERNEL_FUNNEL)
876     thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
877 #endif
878     AFS_ASSERT_GLOCK();
879     AFS_GUNLOCK();
880 #if     defined(AFS_HPUX102_ENV)
881 #if     defined(AFS_HPUX110_ENV)
882     /* we need a file associated with the socket so sosend in NetSend 
883      * will not fail */
884     /* blocking socket */
885     code = socreate(AF_INET, &newSocket, SOCK_DGRAM, 0, 0);
886     fp = falloc();
887     if (!fp)
888         goto bad;
889     fp->f_flag = FREAD | FWRITE;
890     fp->f_type = DTYPE_SOCKET;
891     fp->f_ops = &socketops;
892
893     fp->f_data = (void *)newSocket;
894     newSocket->so_fp = (void *)fp;
895
896 #else /* AFS_HPUX110_ENV */
897     code = socreate(AF_INET, &newSocket, SOCK_DGRAM, 0, SS_NOWAIT);
898 #endif /* else AFS_HPUX110_ENV */
899 #elif defined(AFS_SGI65_ENV) || defined(AFS_OBSD_ENV)
900     code = socreate(AF_INET, &newSocket, SOCK_DGRAM, IPPROTO_UDP);
901 #elif defined(AFS_FBSD50_ENV)
902     code = socreate(AF_INET, &newSocket, SOCK_DGRAM, IPPROTO_UDP,
903                     afs_osi_credp, curthread);
904 #elif defined(AFS_FBSD40_ENV)
905     code = socreate(AF_INET, &newSocket, SOCK_DGRAM, IPPROTO_UDP, curproc);
906 #elif defined(AFS_DARWIN80_ENV)
907     code = sock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, NULL, &newSocket);
908 #else
909     code = socreate(AF_INET, &newSocket, SOCK_DGRAM, 0);
910 #endif /* AFS_HPUX102_ENV */
911     if (code)
912         goto bad;
913
914     memset(&myaddr, 0, sizeof myaddr);
915     myaddr.sin_family = AF_INET;
916     myaddr.sin_port = aport;
917     myaddr.sin_addr.s_addr = ahost;
918 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
919     myaddr.sin_len = sizeof(myaddr);
920 #endif
921
922 #ifdef AFS_HPUX110_ENV
923     bindnam = allocb_wait((addrsize + SO_MSGOFFSET + 1), BPRI_MED);
924     if (!bindnam) {
925         setuerror(ENOBUFS);
926         goto bad;
927     }
928     memcpy((caddr_t) bindnam->b_rptr + SO_MSGOFFSET, (caddr_t) & myaddr,
929            addrsize);
930     bindnam->b_wptr = bindnam->b_rptr + (addrsize + SO_MSGOFFSET + 1);
931
932     code = sobind(newSocket, bindnam, addrsize);
933     if (code) {
934         soclose(newSocket);
935 #if !defined(AFS_HPUX1122_ENV)
936         m_freem(nam);
937 #endif
938         goto bad;
939     }
940
941     freeb(bindnam);
942 #else /* AFS_HPUX110_ENV */
943 #if defined(AFS_DARWIN80_ENV)
944     { 
945        int buflen = 50000;
946        int i,code2;
947        for (i=0;i<2;i++) {
948            code = sock_setsockopt(newSocket, SOL_SOCKET, SO_SNDBUF,
949                                   &buflen, sizeof(buflen));
950            code2 = sock_setsockopt(newSocket, SOL_SOCKET, SO_RCVBUF,
951                                   &buflen, sizeof(buflen));
952            if (!code && !code2)
953                break;
954            if (i == 2)
955               osi_Panic("osi_NewSocket: last attempt to reserve 32K failed!\n");
956            buflen = 32766;
957        }
958     }
959 #else
960     code = soreserve(newSocket, 50000, 50000);
961     if (code) {
962         code = soreserve(newSocket, 32766, 32766);
963         if (code)
964             osi_Panic("osi_NewSocket: last attempt to reserve 32K failed!\n");
965     }
966 #endif
967 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
968 #if defined(AFS_FBSD50_ENV)
969     code = sobind(newSocket, (struct sockaddr *)&myaddr, curthread);
970 #elif defined(AFS_FBSD40_ENV)
971     code = sobind(newSocket, (struct sockaddr *)&myaddr, curproc);
972 #else
973     code = sobind(newSocket, (struct sockaddr *)&myaddr);
974 #endif
975     if (code) {
976         dpf(("sobind fails (%d)\n", (int)code));
977         soclose(newSocket);
978         AFS_GLOCK();
979         goto bad;
980     }
981 #else /* defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV) */
982 #ifdef  AFS_OSF_ENV
983     nam = m_getclr(M_WAIT, MT_SONAME);
984 #else /* AFS_OSF_ENV */
985     nam = m_get(M_WAIT, MT_SONAME);
986 #endif
987     if (nam == NULL) {
988 #if defined(KERNEL_HAVE_UERROR)
989         setuerror(ENOBUFS);
990 #endif
991         goto bad;
992     }
993     nam->m_len = sizeof(myaddr);
994     memcpy(mtod(nam, caddr_t), &myaddr, sizeof(myaddr));
995 #ifdef AFS_SGI65_ENV
996     BHV_PDATA(&bhv) = (void *)newSocket;
997     code = sobind(&bhv, nam);
998     m_freem(nam);
999 #else
1000     code = sobind(newSocket, nam);
1001 #endif
1002     if (code) {
1003         dpf(("sobind fails (%d)\n", (int)code));
1004         soclose(newSocket);
1005 #ifndef AFS_SGI65_ENV
1006         m_freem(nam);
1007 #endif
1008         goto bad;
1009     }
1010 #endif /* else AFS_DARWIN_ENV */
1011 #endif /* else AFS_HPUX110_ENV */
1012
1013     AFS_GLOCK();
1014 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
1015     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
1016 #endif
1017     return (osi_socket *)newSocket;
1018
1019   bad:
1020     AFS_GLOCK();
1021 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
1022     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
1023 #endif
1024     return (osi_socket *)0;
1025 }
1026
1027 osi_socket *
1028 rxk_NewSocket(short aport)
1029 {
1030     return rxk_NewSocketHost(0, aport);
1031 }
1032
1033 /* free socket allocated by rxk_NewSocket */
1034 int
1035 rxk_FreeSocket(register struct socket *asocket)
1036 {
1037     AFS_STATCNT(osi_FreeSocket);
1038 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
1039     thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
1040 #endif
1041 #ifdef AFS_HPUX110_ENV
1042     if (asocket->so_fp) {
1043         struct file *fp = asocket->so_fp;
1044 #if !defined(AFS_HPUX1123_ENV)
1045         /* 11.23 still has falloc, but not FPENTRYFREE ! 
1046          * so for now if we shutdown, we will waist a file 
1047          * structure */
1048         FPENTRYFREE(fp);
1049         asocket->so_fp = NULL;
1050 #endif
1051     }
1052 #endif /* AFS_HPUX110_ENV */
1053     soclose(asocket);
1054 #if defined(AFS_DARWIN_ENV) && defined(KERNEL_FUNNEL)
1055     thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
1056 #endif
1057     return 0;
1058 }
1059 #endif /* !SUN5 && !LINUX20 */
1060
1061 #if defined(RXK_LISTENER_ENV) || defined(AFS_SUN5_ENV)
1062 /*
1063  * Run RX event daemon every second (5 times faster than rest of systems)
1064  */
1065 void
1066 afs_rxevent_daemon(void)
1067 {
1068     struct clock temp;
1069     SPLVAR;
1070
1071     while (1) {
1072 #ifdef RX_ENABLE_LOCKS
1073         AFS_GUNLOCK();
1074 #endif /* RX_ENABLE_LOCKS */
1075         NETPRI;
1076         rxevent_RaiseEvents(&temp);
1077         USERPRI;
1078 #ifdef RX_ENABLE_LOCKS
1079         AFS_GLOCK();
1080 #endif /* RX_ENABLE_LOCKS */
1081 #ifdef RX_KERNEL_TRACE
1082         afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
1083                    "before afs_osi_Wait()");
1084 #endif
1085         afs_osi_Wait(500, NULL, 0);
1086 #ifdef RX_KERNEL_TRACE
1087         afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
1088                    "after afs_osi_Wait()");
1089 #endif
1090         if (afs_termState == AFSOP_STOP_RXEVENT) {
1091 #ifdef RXK_LISTENER_ENV
1092             afs_termState = AFSOP_STOP_RXK_LISTENER;
1093 #else
1094 #ifdef AFS_SUN510_ENV
1095             afs_termState = AFSOP_STOP_NETIF;
1096 #else
1097             afs_termState = AFSOP_STOP_COMPLETE;
1098 #endif
1099 #endif
1100             osi_rxWakeup(&afs_termState);
1101             return;
1102         }
1103     }
1104 }
1105 #endif
1106
1107 #ifdef RXK_LISTENER_ENV
1108
1109 /* rxk_ReadPacket returns 1 if valid packet, 0 on error. */
1110 int
1111 rxk_ReadPacket(osi_socket so, struct rx_packet *p, int *host, int *port)
1112 {
1113     int code;
1114     struct sockaddr_in from;
1115     int nbytes;
1116     afs_int32 rlen;
1117     register afs_int32 tlen;
1118     afs_int32 savelen;          /* was using rlen but had aliasing problems */
1119     rx_computelen(p, tlen);
1120     rx_SetDataSize(p, tlen);    /* this is the size of the user data area */
1121
1122     tlen += RX_HEADER_SIZE;     /* now this is the size of the entire packet */
1123     rlen = rx_maxJumboRecvSize; /* this is what I am advertising.  Only check
1124                                  * it once in order to avoid races.  */
1125     tlen = rlen - tlen;
1126     if (tlen > 0) {
1127         tlen = rxi_AllocDataBuf(p, tlen, RX_PACKET_CLASS_RECV_CBUF);
1128         if (tlen > 0) {
1129             tlen = rlen - tlen;
1130         } else
1131             tlen = rlen;
1132     } else
1133         tlen = rlen;
1134
1135     /* add some padding to the last iovec, it's just to make sure that the 
1136      * read doesn't return more data than we expect, and is done to get around
1137      * our problems caused by the lack of a length field in the rx header. */
1138     savelen = p->wirevec[p->niovecs - 1].iov_len;
1139     p->wirevec[p->niovecs - 1].iov_len = savelen + RX_EXTRABUFFERSIZE;
1140
1141     nbytes = tlen + sizeof(afs_int32);
1142 #ifdef RX_KERNEL_TRACE
1143     if (ICL_SETACTIVE(afs_iclSetp)) {
1144         AFS_GLOCK();
1145         afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
1146                    "before osi_NetRecive()");
1147         AFS_GUNLOCK();
1148     }
1149 #endif
1150     code = osi_NetReceive(rx_socket, &from, p->wirevec, p->niovecs, &nbytes);
1151
1152 #ifdef RX_KERNEL_TRACE
1153     if (ICL_SETACTIVE(afs_iclSetp)) {
1154         AFS_GLOCK();
1155         afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
1156                    "after osi_NetRecive()");
1157         AFS_GUNLOCK();
1158     }
1159 #endif
1160     /* restore the vec to its correct state */
1161     p->wirevec[p->niovecs - 1].iov_len = savelen;
1162
1163     if (!code) {
1164         p->length = nbytes - RX_HEADER_SIZE;;
1165         if ((nbytes > tlen) || (p->length & 0x8000)) {  /* Bogus packet */
1166             if (nbytes <= 0) {
1167                 MUTEX_ENTER(&rx_stats_mutex);
1168                 rx_stats.bogusPacketOnRead++;
1169                 rx_stats.bogusHost = from.sin_addr.s_addr;
1170                 MUTEX_EXIT(&rx_stats_mutex);
1171                 dpf(("B: bogus packet from [%x,%d] nb=%d",
1172                      from.sin_addr.s_addr, from.sin_port, nbytes));
1173             }
1174             return -1;
1175         } else {
1176             /* Extract packet header. */
1177             rxi_DecodePacketHeader(p);
1178
1179             *host = from.sin_addr.s_addr;
1180             *port = from.sin_port;
1181             if (p->header.type > 0 && p->header.type < RX_N_PACKET_TYPES) {
1182                 MUTEX_ENTER(&rx_stats_mutex);
1183                 rx_stats.packetsRead[p->header.type - 1]++;
1184                 MUTEX_EXIT(&rx_stats_mutex);
1185             }
1186
1187             /* Free any empty packet buffers at the end of this packet */
1188             rxi_TrimDataBufs(p, 1);
1189
1190             return 0;
1191         }
1192     } else
1193         return code;
1194 }
1195
1196 /* rxk_Listener() 
1197  *
1198  * Listen for packets on socket. This thread is typically started after
1199  * rx_Init has called rxi_StartListener(), but nevertheless, ensures that
1200  * the start state is set before proceeding.
1201  *
1202  * Note that this thread is outside the AFS global lock for much of
1203  * it's existence.
1204  *
1205  * In many OS's, the socket receive code sleeps interruptibly. That's not what
1206  * we want here. So we need to either block all signals (including SIGKILL
1207  * and SIGSTOP) or reset the thread's signal state to unsignalled when the
1208  * OS's socket receive routine returns as a result of a signal.
1209  */
1210 int rxk_ListenerPid;            /* Used to signal process to wakeup at shutdown */
1211 #ifdef AFS_LINUX20_ENV
1212 struct task_struct *rxk_ListenerTask;
1213 #endif
1214
1215 #ifdef AFS_SUN5_ENV
1216 /*
1217  * Run the listener as a kernel thread.
1218  */
1219 void
1220 rxk_Listener(void)
1221 {
1222     extern id_t syscid;
1223     void rxk_ListenerProc(void);
1224     if (thread_create
1225         (NULL, DEFAULTSTKSZ, rxk_ListenerProc, 0, 0, &p0, TS_RUN,
1226          minclsyspri) == NULL)
1227         osi_Panic("rxk_Listener: failed to start listener thread!\n");
1228 }
1229
1230 void
1231 rxk_ListenerProc(void)
1232 #else /* AFS_SUN5_ENV */
1233 void
1234 rxk_Listener(void)
1235 #endif                          /* AFS_SUN5_ENV */
1236 {
1237     struct rx_packet *rxp = NULL;
1238     int code;
1239     int host, port;
1240
1241 #ifdef AFS_LINUX20_ENV
1242     rxk_ListenerPid = current->pid;
1243     rxk_ListenerTask = current;
1244 #endif
1245 #ifdef AFS_SUN5_ENV
1246     rxk_ListenerPid = 1;        /* No PID, just a flag that we're alive */
1247 #endif /* AFS_SUN5_ENV */
1248 #ifdef AFS_XBSD_ENV
1249     rxk_ListenerPid = curproc->p_pid;
1250 #endif /* AFS_FBSD_ENV */
1251 #ifdef AFS_DARWIN80_ENV
1252     rxk_ListenerPid = proc_selfpid();
1253 #elif defined(AFS_DARWIN_ENV)
1254     rxk_ListenerPid = current_proc()->p_pid;
1255 #endif
1256 #if defined(RX_ENABLE_LOCKS) && !defined(AFS_SUN5_ENV)
1257     AFS_GUNLOCK();
1258 #endif /* RX_ENABLE_LOCKS && !AFS_SUN5_ENV */
1259     while (afs_termState != AFSOP_STOP_RXK_LISTENER) {
1260         if (rxp) {
1261             rxi_RestoreDataBufs(rxp);
1262         } else {
1263             rxp = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE);
1264             if (!rxp)
1265                 osi_Panic("rxk_Listener: No more Rx buffers!\n");
1266         }
1267         if (!(code = rxk_ReadPacket(rx_socket, rxp, &host, &port))) {
1268             rxp = rxi_ReceivePacket(rxp, rx_socket, host, port, 0, 0);
1269         }
1270     }
1271
1272 #ifdef RX_ENABLE_LOCKS
1273     AFS_GLOCK();
1274 #endif /* RX_ENABLE_LOCKS */
1275     if (afs_termState == AFSOP_STOP_RXK_LISTENER) {
1276 #ifdef AFS_SUN510_ENV
1277         afs_termState = AFSOP_STOP_NETIF;
1278 #else
1279         afs_termState = AFSOP_STOP_COMPLETE;
1280 #endif
1281         osi_rxWakeup(&afs_termState);
1282     }
1283     rxk_ListenerPid = 0;
1284 #ifdef AFS_LINUX20_ENV
1285     rxk_ListenerTask = 0;
1286     osi_rxWakeup(&rxk_ListenerTask);
1287 #endif
1288 #if defined(AFS_SUN5_ENV)
1289     osi_rxWakeup(&rxk_ListenerPid);
1290 #endif
1291 #ifdef AFS_SUN5_ENV
1292     AFS_GUNLOCK();
1293 #endif /* AFS_SUN5_ENV */
1294 }
1295
1296 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_SUN5_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
1297 /* The manner of stopping the rx listener thread may vary. Most unix's should
1298  * be able to call soclose.
1299  */
1300 void
1301 osi_StopListener(void)
1302 {
1303     soclose(rx_socket);
1304 }
1305 #endif
1306 #endif /* RXK_LISTENER_ENV */
1307
1308 #endif /* !NCR && !UKERNEL */