2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include "../afs/param.h"
12 #include "../rx/rx_kcommon.h"
17 #include "../inet/common.h"
18 #include "../sys/tiuser.h"
19 #include "../sys/t_kuser.h"
20 #include "../sys/stropts.h"
21 #include "../sys/stream.h"
22 #include "../sys/tihdr.h"
23 #include "../sys/fcntl.h"
25 #include "../netinet/ip6.h"
27 #include "../inet/ip.h"
28 #include "../netinet/udp.h"
31 * Function pointers for kernel socket routines
33 struct sonode *(*sockfs_socreate)
34 (vnode_t *, int, int, int, int, struct sonode *, int *) = NULL;
35 struct vnode *(*sockfs_solookup)
36 (int, int, int, char *, int *) = NULL;
38 (struct sonode *, struct sockaddr *, int, int, int) = NULL;
39 int (*sockfs_sorecvmsg)
40 (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
41 int (*sockfs_sosendmsg)
42 (struct sonode *, struct nmsghdr *, struct uio *) = NULL;
43 int (*sockfs_sosetsockopt)
44 (struct sonode *, int, int, void *, int) = NULL;
51 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
55 struct sockaddr_in rx_sockaddr;
57 /* Allocate a new socket at specified port in network byte order. */
58 struct osi_socket *rxk_NewSocket(short aport)
62 struct sockaddr_in addr;
66 AFS_STATCNT(osi_NewSocket);
68 if (sockfs_solookup == NULL) {
69 sockfs_solookup = (struct vnode *(*)())modlookup("sockfs", "solookup");
70 if (sockfs_solookup == NULL) {
74 if (sockfs_socreate == NULL) {
75 sockfs_socreate = (struct sonode *(*)())modlookup("sockfs", "socreate");
76 if (sockfs_socreate == NULL) {
80 if (sockfs_sobind == NULL) {
81 sockfs_sobind = (int (*)())modlookup("sockfs", "sobind");
82 if (sockfs_sobind == NULL) {
86 if (sockfs_sosetsockopt == NULL) {
87 sockfs_sosetsockopt = (int (*)())modlookup("sockfs", "sosetsockopt");
88 if (sockfs_sosetsockopt == NULL) {
92 if (sockfs_sosendmsg == NULL) {
93 sockfs_sosendmsg = (int (*)())modlookup("sockfs", "sosendmsg");
94 if (sockfs_sosendmsg == NULL) {
98 if (sockfs_sorecvmsg == NULL) {
99 sockfs_sorecvmsg = (int (*)())modlookup("sockfs", "sorecvmsg");
100 if (sockfs_sorecvmsg == NULL) {
105 accessvp = sockfs_solookup(AF_INET, SOCK_DGRAM, 0, "/dev/udp", &error);
106 if (accessvp == NULL) {
110 so = sockfs_socreate(accessvp, AF_INET, SOCK_DGRAM, 0,
111 SOV_STREAM, NULL, &error);
116 addr.sin_family = AF_INET;
117 addr.sin_port = aport;
118 addr.sin_addr.s_addr = INADDR_ANY;
119 error = sockfs_sobind(so, (struct sockaddr *)&addr, sizeof(addr), 0, 0);
125 error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len));
131 error = sockfs_sosetsockopt(so, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
136 return (struct osi_socket *)so;
139 int osi_FreeSocket(asocket)
140 register struct osi_socket *asocket;
142 extern int rxk_ListenerPid;
143 struct sonode *so = (struct sonode *)asocket;
144 vnode_t *vp = SOTOV(so);
146 AFS_STATCNT(osi_FreeSocket);
148 kill(rxk_ListenerPid, SIGUSR1);
152 int osi_NetSend(asocket, addr, dvec, nvecs, asize, istack)
153 struct osi_socket *asocket;
154 struct sockaddr_in *addr;
160 struct sonode *so = (struct sonode *)asocket;
163 struct iovec iov[RX_MAXIOVECS];
167 if (nvecs > RX_MAXIOVECS) {
168 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
171 msg.msg_name = (struct sockaddr *)addr;
172 msg.msg_namelen = sizeof(struct sockaddr_in);
174 msg.msg_iovlen = nvecs;
175 msg.msg_control = NULL;
176 msg.msg_controllen = 0;
179 for (i = 0 ; i < nvecs ; i++) {
180 iov[i].iov_base = dvec[i].iov_base;
181 iov[i].iov_len = dvec[i].iov_len;
183 uio.uio_iov = &iov[0];
184 uio.uio_iovcnt = nvecs;
186 uio.uio_segflg = UIO_SYSSPACE;
187 uio.uio_fmode = FREAD|FWRITE;
189 uio.uio_resid = asize;
191 error = sockfs_sosendmsg(so, &msg, &uio);
196 int osi_NetReceive(asocket, addr, dvec, nvecs, alength)
197 struct osi_socket *asocket;
198 struct sockaddr_in *addr;
203 struct sonode *so = (struct sonode *)asocket;
206 struct iovec iov[RX_MAXIOVECS];
210 if (nvecs > RX_MAXIOVECS) {
211 osi_Panic("osi_NetSend: %d: Too many iovecs.\n", nvecs);
215 msg.msg_namelen = sizeof(struct sockaddr_in);
218 msg.msg_control = NULL;
219 msg.msg_controllen = 0;
222 for (i = 0 ; i < nvecs ; i++) {
223 iov[i].iov_base = dvec[i].iov_base;
224 iov[i].iov_len = dvec[i].iov_len;
226 uio.uio_iov = &iov[0];
227 uio.uio_iovcnt = nvecs;
229 uio.uio_segflg = UIO_SYSSPACE;
232 uio.uio_resid = *alength;
234 error = sockfs_sorecvmsg(so, &msg, &uio);
236 if (msg.msg_name == NULL) {
239 bcopy(msg.msg_name, addr, msg.msg_namelen);
240 kmem_free(msg.msg_name, msg.msg_namelen);
241 *alength = *alength - uio.uio_resid;
245 if (error == EINTR && ISSIG(curthread, FORREAL)) {
246 klwp_t *lwp = ttolwp(curthread);
247 proc_t *p = ttoproc(curthread);
248 int sig = lwp->lwp_cursig;
250 if (sig == SIGKILL) {
251 mutex_enter(&p->p_lock);
252 p->p_flag &= ~SKILLED;
253 mutex_exit(&p->p_lock);
256 if (lwp->lwp_curinfo) {
257 siginfofree(lwp->lwp_curinfo);
258 lwp->lwp_curinfo = NULL;
265 void shutdown_rxkernel(void)
269 void osi_StopListener(void)
271 osi_FreeSocket(rx_socket);
274 #else /* AFS_SUN56_ENV */
276 #include "../inet/common.h"
277 #include "../sys/tiuser.h"
278 #include "../sys/t_kuser.h"
279 #include "../sys/ioctl.h"
280 #include "../sys/stropts.h"
281 #include "../sys/stream.h"
282 #include "../sys/strsubr.h"
283 #include "../sys/vnode.h"
284 #include "../sys/stropts.h"
285 #include "../sys/tihdr.h"
286 #include "../sys/timod.h"
287 #include "../sys/fcntl.h"
288 #include "../sys/debug.h"
289 #include "../inet/common.h"
290 #include "../inet/mi.h"
291 #include "../netinet/udp.h"
293 extern dev_t afs_udp_rdev;
302 /* rxi_NewSocket, rxi_FreeSocket and osi_NetSend are from the now defunct
306 dev_t afs_udp_rdev = (dev_t)0;
308 /* Allocate a new socket at specified port in network byte order. */
309 struct osi_socket *rxk_NewSocket(short aport)
312 struct t_bind *reqp, *rspp;
314 struct sockaddr_in *myaddrp;
318 AFS_STATCNT(osi_NewSocket);
319 afs_udp_rdev = makedevice(11 /*CLONE*/, ddi_name_to_major("udp"));
320 code = t_kopen(NULL, afs_udp_rdev, FREAD|FWRITE, &udp_tiptr, CRED());
322 return (struct osi_socket *)0;
325 code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&reqp);
327 t_kclose(udp_tiptr, 0);
329 code = t_kalloc(udp_tiptr, T_BIND, T_ADDR, (char **)&rspp);
331 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
332 t_kclose(udp_tiptr, 0);
333 return (struct osi_socket *)0;
336 reqp->addr.len = sizeof(struct sockaddr_in);
337 myaddrp = (struct sockaddr_in *) reqp->addr.buf;
338 myaddrp->sin_family = AF_INET;
339 myaddrp->sin_port = aport;
340 myaddrp->sin_addr.s_addr = INADDR_ANY; /* XXX Was 0 XXX */
342 code = t_kbind(udp_tiptr, reqp, rspp);
344 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
345 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
346 t_kclose(udp_tiptr, 0);
347 return (struct osi_socket *)0;
349 if (bcmp(reqp->addr.buf, rspp->addr.buf, rspp->addr.len)) {
350 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
351 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
352 t_kclose(udp_tiptr, 0);
353 return (struct osi_socket *)0;
355 t_kfree(udp_tiptr, (char *)reqp, T_BIND);
356 t_kfree(udp_tiptr, (char *)rspp, T_BIND);
359 * Set the send and receive buffer sizes.
361 stp = udp_tiptr->fp->f_vnode->v_stream;
363 q->q_hiwat = rx_UdpBufSize;
364 q->q_next->q_hiwat = rx_UdpBufSize;
365 RD(q)->q_hiwat = rx_UdpBufSize;
367 return (struct osi_socket *) udp_tiptr;
371 int osi_FreeSocket(asocket)
372 register struct osi_socket *asocket;
374 extern int rxk_ListenerPid;
375 TIUSER *udp_tiptr = (TIUSER *) asocket;
376 AFS_STATCNT(osi_FreeSocket);
379 kill(rxk_ListenerPid, SIGUSR1);
384 int osi_NetSend(asocket, addr, dvec, nvecs, asize, istack)
385 register struct osi_socket *asocket;
388 register afs_int32 asize;
389 struct sockaddr_in *addr;
394 TIUSER *udp_tiptr = (TIUSER *) asocket;
395 struct t_kunitdata *udreq;
396 struct sockaddr_in sin;
401 * XXX We don't do any checking on the family since it's assumed to be
404 sin.sin_family = AF_INET;
405 sin.sin_addr.s_addr = addr->sin_addr.s_addr;
406 sin.sin_port = addr->sin_port;
409 * Get a buffer for the RX header
412 osi_Panic("osi_NetSend, nvecs=%d\n", nvecs);
414 while (!(bp = allocb(dvec[0].iov_len, BPRI_LO))) {
415 if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
420 /* Copy the data into the buffer */
421 bcopy((char *)dvec[0].iov_base, (char *)bp->b_wptr, dvec[0].iov_len);
422 bp->b_datap->db_type = M_DATA;
423 bp->b_wptr += dvec[0].iov_len;
426 * Append each element in the iovec to the buffer
428 for (i = 1 ; i < nvecs ; i++) {
429 /* Get a buffer for the next chunk */
430 while (!(dbp = allocb(dvec[i].iov_len, BPRI_LO))) {
431 if (strwaitbuf(dvec[i].iov_len, BPRI_LO)) {
437 /* Copy the data into the buffer */
438 bcopy((char *)dvec[i].iov_base, (char *)dbp->b_wptr, dvec[i].iov_len);
439 dbp->b_datap->db_type = M_DATA;
440 dbp->b_wptr += dvec[i].iov_len;
442 /* Append it to the message buffer */
447 * Allocate and format the unitdata structure.
449 code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
452 printf("osi_NetSend: t_kalloc failed %d\n", code);
455 udreq->addr.len = sizeof(struct sockaddr_in);
456 udreq->addr.maxlen = sizeof(struct sockaddr_in);
457 udreq->addr.buf = (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
459 udreq->opt.maxlen = 0;
460 bcopy((char *)&sin, udreq->addr.buf, sizeof(struct sockaddr_in));
461 udreq->udata.udata_mp = bp;
462 udreq->udata.len = asize;
464 code = t_ksndudata(udp_tiptr, udreq, NULL);
466 printf("osi_NetSend: t_ksndudata failed %d\n", code);
469 t_kfree(udp_tiptr, (caddr_t)udreq, T_UNITDATA);
474 int osi_NetReceive(asocket, addr, dvec, nvecs, alength)
475 struct osi_socket *asocket;
476 struct sockaddr_in *addr;
482 TIUSER *udp_tiptr = (TIUSER *) asocket;
483 struct t_kunitdata *udreq;
497 * Allocate the unitdata structure.
499 code = t_kalloc(udp_tiptr, T_UNITDATA, T_UDATA, (char **)&udreq);
501 printf("osi_NetReceive: t_kalloc failed %d\n", code);
504 udreq->addr.len = sizeof(struct sockaddr_in);
505 udreq->addr.maxlen = sizeof(struct sockaddr_in);
506 udreq->addr.buf = (char *)kmem_alloc(sizeof(struct sockaddr_in), KM_SLEEP);
508 udreq->opt.maxlen = 0;
511 * Loop until we get an error or receive some data.
515 * Wait until there is something to do
517 code = t_kspoll(udp_tiptr, -1, READWAIT, &events);
519 osi_Panic("osi_NetReceive, infinite t_kspoll timed out\n");
522 * If there is a message then read it in
525 code = t_krcvudata(udp_tiptr, udreq, &type, &error);
529 * Block attempts to kill this thread
531 if (code == EINTR && ISSIG(curthread, FORREAL)) {
532 klwp_t *lwp = ttolwp(curthread);
533 proc_t *p = ttoproc(curthread);
534 int sig = lwp->lwp_cursig;
536 if (sig == SIGKILL) {
537 mutex_enter(&p->p_lock);
538 p->p_flag &= ~SKILLED;
539 mutex_exit(&p->p_lock);
542 if (lwp->lwp_curinfo) {
543 kmem_free((caddr_t)lwp->lwp_curinfo, sizeof(*lwp->lwp_curinfo));
544 lwp->lwp_curinfo = NULL;
553 * Ignore non-data message types
555 if (type != T_DATA) {
560 * Save the source address
562 bcopy(udreq->addr.buf, (char *)addr, sizeof(struct sockaddr_in));
565 * Copy out the message buffers, take care not to overflow
568 dbp = udreq->udata.udata_mp;
570 for (i = 0 ; dbp != NULL && length > 0 && i < nvecs ; i++) {
571 tlen = dvec[i].iov_len;
572 tbase = dvec[i].iov_base;
576 while (dbp != NULL && tlen > 0) {
577 blen = dbp->b_wptr - dbp->b_rptr;
579 bcopy((char *)dbp->b_rptr, tbase, tlen);
584 bcopy((char *)dbp->b_rptr, tbase, blen);
592 *alength = *alength - length;
596 t_kfree(udp_tiptr, (caddr_t)udreq, T_UNITDATA);
601 void osi_StopListener(void)
603 osi_FreeSocket(rx_socket);
607 void shutdown_rxkernel(void)
612 #endif /* AFS_SUN56_ENV */
613 #endif /* AFS_SUN5_ENV */