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