Whamcloud - gitweb
1f3503cd515196b5029add75d9c9dbc4b3ca1981
[fs/lustre-release.git] / libcfs / libcfs / darwin / darwin-tcpip.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * libcfs/libcfs/darwin/darwin-tcpip.c
37  *
38  * Darwin porting library
39  * Make things easy to port
40  *
41  * Author: Phil Schwan <phil@clusterfs.com>
42  */
43
44 #include <mach/mach_types.h>
45 #include <sys/file.h>
46 #include <sys/mount.h>
47 #include <string.h>
48 #include <netinet/in.h>
49 #include <netinet/tcp.h>
50 #include <sys/socket.h>
51 #include <sys/socketvar.h>
52 #include <sys/sockio.h>
53 #include <sys/protosw.h>
54 #include <net/if.h>
55
56 #define DEBUG_SUBSYSTEM S_LNET
57
58 #include <libcfs/libcfs.h>
59
60 static __inline__ struct sockaddr_in
61 blank_sin()
62 {
63         struct sockaddr_in  blank = { sizeof(struct sockaddr_in), AF_INET };
64         return (blank);
65 }
66
67 void
68 libcfs_ipif_free_enumeration (char **names, int n)
69 {
70         int      i;
71
72         LASSERT (n > 0);
73
74         for (i = 0; i < n && names[i] != NULL; i++)
75                 LIBCFS_FREE(names[i], IFNAMSIZ);
76                 
77         LIBCFS_FREE(names, n * sizeof(*names));
78 }
79
80 #ifdef __DARWIN8__
81 /*
82  * Darwin 8.x 
83  *
84  * No hack kernel structre, all using KPI.
85  */
86
87 int
88 libcfs_ipif_query (char *name, int *up, __u32 *ip, __u32 *mask)
89 {
90         struct ifreq    ifr;
91         socket_t        so;
92         __u32           val;
93         int             nob;
94         int             rc;
95
96         rc = -sock_socket(PF_INET, SOCK_STREAM, 0, 
97                           NULL, NULL, &so);
98         if (rc != 0) {
99                 CERROR ("Can't create socket: %d\n", rc);
100                 return rc;
101         }
102
103         nob = strnlen(name, IFNAMSIZ);
104         if (nob == IFNAMSIZ) {
105                 CERROR("Interface name %s too long\n", name);
106                 rc = -EINVAL;
107                 goto out;
108         }
109
110         CLASSERT (sizeof(ifr.ifr_name) >= IFNAMSIZ);
111         bzero(&ifr, sizeof(ifr));
112         strcpy(ifr.ifr_name, name);
113         rc = -sock_ioctl (so, SIOCGIFFLAGS, &ifr);
114
115         if (rc != 0) {
116                 CERROR("Can't get flags for interface %s\n", name);
117                 goto out;
118         }
119         
120         if ((ifr.ifr_flags & IFF_UP) == 0) {
121                 CDEBUG(D_NET, "Interface %s down\n", name);
122                 *up = 0;
123                 *ip = *mask = 0;
124                 goto out;
125         }
126
127         *up = 1;
128
129         bzero(&ifr, sizeof(ifr));
130         strcpy(ifr.ifr_name, name);
131         *((struct sockaddr_in *)&ifr.ifr_addr) = blank_sin();
132         rc = -sock_ioctl(so, SIOCGIFADDR, &ifr);
133
134         if (rc != 0) {
135                 CERROR("Can't get IP address for interface %s\n", name);
136                 goto out;
137         }
138         
139         val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
140         *ip = ntohl(val);
141
142         bzero(&ifr, sizeof(ifr));
143         strcpy(ifr.ifr_name, name);
144         *((struct sockaddr_in *)&ifr.ifr_addr) = blank_sin();
145         rc = -sock_ioctl(so, SIOCGIFNETMASK, &ifr);
146
147         if (rc != 0) {
148                 CERROR("Can't get netmask for interface %s\n", name);
149                 goto out;
150         }
151
152         val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
153         *mask = ntohl(val);
154 out:
155         sock_close(so);
156         return rc;
157 }
158
159 int
160 libcfs_ipif_enumerate (char ***namesp)
161 {
162         /* Allocate and fill in 'names', returning # interfaces/error */
163         char           **names;
164         int             toobig;
165         int             nalloc;
166         int             nfound;
167         socket_t        so;
168         struct ifreq   *ifr;
169         struct ifconf   ifc;
170         int             rc;
171         int             nob;
172         int             i;
173
174         rc = -sock_socket(PF_INET, SOCK_STREAM, 0, 
175                           NULL, NULL, &so);
176         if (rc != 0) {
177                 CERROR ("Can't create socket: %d\n", rc);
178                 return (rc);
179         }
180
181         nalloc = 16;    /* first guess at max interfaces */
182         toobig = 0;
183         for (;;) {
184                 if (nalloc * sizeof(*ifr) > CFS_PAGE_SIZE) {
185                         toobig = 1;
186                         nalloc = CFS_PAGE_SIZE/sizeof(*ifr);
187                         CWARN("Too many interfaces: only enumerating first %d\n",
188                               nalloc);
189                 }
190
191                 LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr));
192                 if (ifr == NULL) {
193                         CERROR ("ENOMEM enumerating up to %d interfaces\n", nalloc);
194                                 rc = -ENOMEM;
195                         goto out0;
196                 }
197                                 
198                 ifc.ifc_buf = (char *)ifr;
199                 ifc.ifc_len = nalloc * sizeof(*ifr);
200                                         
201 #if 1
202                 /*
203                  * XXX Liang:
204                  * sock_ioctl(..., SIOCGIFCONF, ...) is not supposed to be used in
205                  * kernel space because it always try to copy result to userspace. 
206                  * So we can't get interfaces name by sock_ioctl(...,SIOCGIFCONF,...).
207                  * I've created a bug for Apple, let's wait...
208                  */
209                 nfound = 0;
210                 for (i = 0; i < 16; i++) {
211                         struct ifreq    en;
212                         bzero(&en, sizeof(en));
213                         snprintf(en.ifr_name, IFNAMSIZ, "en%d", i);
214                         rc = -sock_ioctl (so, SIOCGIFFLAGS, &en);
215                         if (rc != 0)
216                                 continue;
217                         strcpy(ifr[nfound++].ifr_name, en.ifr_name);
218                 }
219
220 #else           /* NOT in using now */
221                 rc = -sock_ioctl(so, SIOCGIFCONF, (caddr_t)&ifc);
222                                 
223                 if (rc < 0) {
224                         CERROR ("Error %d enumerating interfaces\n", rc);
225                         goto out1;
226                 }
227
228                 nfound = ifc.ifc_len/sizeof(*ifr);
229                 LASSERT (nfound <= nalloc);
230 #endif
231
232                 if (nfound < nalloc || toobig)
233                         break;
234
235                 LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
236                 nalloc *= 2;
237         }
238         if (nfound == 0)
239                 goto out1;
240
241         LIBCFS_ALLOC(names, nfound * sizeof(*names));
242         if (names == NULL) {
243                 rc = -ENOMEM;
244                 goto out1;
245         }
246         /* NULL out all names[i] */
247         memset (names, 0, nfound * sizeof(*names));
248
249         for (i = 0; i < nfound; i++) {
250
251                 nob = strnlen (ifr[i].ifr_name, IFNAMSIZ);
252                 if (nob == IFNAMSIZ) {
253                         /* no space for terminating NULL */
254                         CERROR("interface name %.*s too long (%d max)\n",
255                                nob, ifr[i].ifr_name, IFNAMSIZ);
256                         rc = -ENAMETOOLONG;
257                         goto out2;
258                 }
259
260                 LIBCFS_ALLOC(names[i], IFNAMSIZ);
261                 if (names[i] == NULL) {
262                         rc = -ENOMEM;
263                         goto out2;
264                 }
265
266                 memcpy(names[i], ifr[i].ifr_name, nob);
267                 names[i][nob] = 0;
268         }
269
270         *namesp = names;
271         rc = nfound;
272
273 out2:
274         if (rc < 0)
275                 libcfs_ipif_free_enumeration(names, nfound);
276 out1:
277         LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
278 out0:
279         sock_close(so);
280         return rc;
281
282 }
283
284 /*
285  * Public entry of socket upcall.
286  *
287  * so_upcall can only be installed while create/accept of socket in 
288  * Darwin 8.0, so we setup libcfs_sock_upcall() as upcall for all 
289  * sockets in creat/accept, it will call upcall provided by user 
290  * which can be setup after create/accept of socket.
291  */
292 static void libcfs_sock_upcall(socket_t so, void* arg, int waitf)
293 {
294         cfs_socket_t    *sock;
295
296         sock = (cfs_socket_t *)arg;
297         LASSERT(sock->s_magic == CFS_SOCK_MAGIC);
298
299         if ((sock->s_flags & CFS_SOCK_UPCALL) != 0 && sock->s_upcall != NULL)
300                 sock->s_upcall(so, sock->s_upcallarg, waitf);
301         return;
302 }
303
304 void libcfs_sock_set_cb(cfs_socket_t *sock, so_upcall callback, void *arg)
305 {
306         sock->s_upcall = callback;
307         sock->s_upcallarg = arg;
308         sock->s_flags |= CFS_SOCK_UPCALL;
309         return;
310 }
311
312 void libcfs_sock_reset_cb(cfs_socket_t *sock)
313 {
314         sock->s_flags &= ~CFS_SOCK_UPCALL;
315         sock->s_upcall = NULL;
316         sock->s_upcallarg = NULL;
317         return;
318 }
319
320 static int
321 libcfs_sock_create (cfs_socket_t **sockp, int *fatal,
322                     __u32 local_ip, int local_port)
323 {
324         struct sockaddr_in  locaddr;
325         cfs_socket_t    *sock;
326         int             option;
327         int             optlen;
328         int             rc;
329
330         /* All errors are fatal except bind failure if the port is in use */
331         *fatal = 1;
332
333         sock = _MALLOC(sizeof(cfs_socket_t), M_TEMP, M_WAITOK|M_ZERO);
334         if (!sock) {
335                 CERROR("Can't allocate cfs_socket.\n");
336                 return -ENOMEM;
337         }
338         *sockp = sock;
339         sock->s_magic = CFS_SOCK_MAGIC;
340
341         rc = -sock_socket(PF_INET, SOCK_STREAM, 0, 
342                           libcfs_sock_upcall, sock, &C2B_SOCK(sock));
343         if (rc != 0) 
344                 goto out;
345         option = 1;
346         optlen = sizeof(option);
347         rc = -sock_setsockopt(C2B_SOCK(sock), SOL_SOCKET, 
348                               SO_REUSEADDR, &option, optlen);
349         if (rc != 0)
350                 goto out;
351
352         /* can't specify a local port without a local IP */
353         LASSERT (local_ip == 0 || local_port != 0);
354
355         if (local_ip != 0 || local_port != 0) {
356                 bzero (&locaddr, sizeof (locaddr));
357                 locaddr.sin_len = sizeof(struct sockaddr_in);
358                 locaddr.sin_family = AF_INET;
359                 locaddr.sin_port = htons (local_port);
360                 locaddr.sin_addr.s_addr = (local_ip != 0) ? htonl(local_ip) : INADDR_ANY;
361                 rc = -sock_bind(C2B_SOCK(sock), (struct sockaddr *)&locaddr);
362                 if (rc == -EADDRINUSE) {
363                         CDEBUG(D_NET, "Port %d already in use\n", local_port);
364                         *fatal = 0;
365                         goto out;
366                 }
367                 if (rc != 0) {
368                         CERROR("Error trying to bind to port %d: %d\n",
369                                local_port, rc);
370                         goto out;
371                 }
372         }
373         return 0;
374 out:
375         if (C2B_SOCK(sock) != NULL) 
376                 sock_close(C2B_SOCK(sock));
377         FREE(sock, M_TEMP);
378         return rc;
379 }
380
381 int
382 libcfs_sock_listen (cfs_socket_t **sockp,
383                    __u32 local_ip, int local_port, int backlog)
384 {
385         cfs_socket_t    *sock;
386         int             fatal;
387         int             rc;
388
389         rc = libcfs_sock_create(&sock, &fatal, local_ip, local_port);
390         if (rc != 0)  {
391                 if (!fatal)
392                         CERROR("Can't create socket: port %d already in use\n",
393                                 local_port);
394                 return rc;
395
396         }
397         rc = -sock_listen(C2B_SOCK(sock), backlog);
398         if (rc == 0) {
399                 *sockp = sock;
400                 return 0;
401         }
402
403         if (C2B_SOCK(sock) != NULL) 
404                 sock_close(C2B_SOCK(sock));
405         FREE(sock, M_TEMP);
406         return rc;
407 }
408
409 int
410 libcfs_sock_accept (cfs_socket_t **newsockp, cfs_socket_t *sock)
411 {
412         cfs_socket_t   *newsock;
413         int             rc;
414
415         newsock = _MALLOC(sizeof(cfs_socket_t), M_TEMP, M_WAITOK|M_ZERO);
416         if (!newsock) {
417                 CERROR("Can't allocate cfs_socket.\n");
418                 return -ENOMEM;
419         }
420         newsock->s_magic = CFS_SOCK_MAGIC;
421         /*
422          * thread will sleep in sock_accept by calling of msleep(), 
423          * it can be interrupted because msleep() use PCATCH as argument.
424          */
425         rc = -sock_accept(C2B_SOCK(sock), NULL, 0, 0, 
426                           libcfs_sock_upcall, newsock, &C2B_SOCK(newsock));
427         if (rc) {
428                 if (C2B_SOCK(newsock) != NULL) 
429                         sock_close(C2B_SOCK(newsock));
430                 FREE(newsock, M_TEMP);
431                 if ((sock->s_flags & CFS_SOCK_DOWN) != 0)
432                         /* shutdown by libcfs_sock_abort_accept(), fake 
433                          * error number for lnet_acceptor() */
434                         rc = -EAGAIN;
435                 return rc;
436         }
437         *newsockp = newsock;
438         return 0;
439 }
440
441 void
442 libcfs_sock_abort_accept (cfs_socket_t *sock)
443 {
444         /*
445          * XXX Liang: 
446          *
447          * we want to wakeup thread blocked by sock_accept, but we don't
448          * know the address where thread is sleeping on, so we cannot 
449          * wakeup it directly.
450          * The thread slept in sock_accept will be waken up while:
451          * 1. interrupt by signal
452          * 2. new connection is coming (sonewconn)
453          * 3. disconnecting of the socket (soisconnected)
454          * 
455          * Cause we can't send signal to a thread directly(no KPI), so the 
456          * only thing can be done here is disconnect the socket (by 
457          * sock_shutdown() or sth else? ).
458          *
459          * Shutdown request of socket with SHUT_WR or SHUT_RDWR will
460          * be issured to the protocol.
461          * sock_shutdown()->tcp_usr_shutdown()->tcp_usrclosed()->
462          * tcp_close()->soisdisconnected(), it will wakeup thread by
463          * wakeup((caddr_t)&so->so_timeo);
464          */
465         sock->s_flags |= CFS_SOCK_DOWN;
466         sock_shutdown(C2B_SOCK(sock), SHUT_RDWR);
467 }
468
469 int
470 libcfs_sock_read (cfs_socket_t *sock, void *buffer, int nob, int timeout)
471 {
472         size_t          rcvlen;
473         int             rc;
474         cfs_duration_t  to = cfs_time_seconds(timeout);
475         cfs_time_t      then;
476         struct timeval  tv;
477
478         LASSERT(nob > 0);
479
480         for (;;) {
481                 struct iovec  iov = {
482                         .iov_base = buffer,
483                         .iov_len  = nob
484                 };
485                 struct  msghdr  msg = {
486                         .msg_name       = NULL,
487                         .msg_namelen    = 0,
488                         .msg_iov        = &iov,
489                         .msg_iovlen     = 1,
490                         .msg_control    = NULL,
491                         .msg_controllen = 0,
492                         .msg_flags      = 0,
493                 };
494                 cfs_duration_usec(to, &tv);
495                 rc = -sock_setsockopt(C2B_SOCK(sock), SOL_SOCKET, SO_RCVTIMEO,
496                                       &tv, sizeof(tv));
497                 if (rc != 0) {
498                         CERROR("Can't set socket recv timeout "
499                                         "%ld.%06d: %d\n",
500                                         (long)tv.tv_sec, (int)tv.tv_usec, rc);
501                         return rc;
502                 }
503
504                 then = cfs_time_current();
505                 rc = -sock_receive(C2B_SOCK(sock), &msg, 0, &rcvlen);
506                 to -= cfs_time_current() - then;
507
508                 if (rc != 0 && rc != -EWOULDBLOCK)
509                         return rc;
510                 if (rcvlen == nob)
511                         return 0;
512
513                 if (to <= 0)
514                         return -EAGAIN;
515
516                 buffer = ((char *)buffer) + rcvlen;
517                 nob -= rcvlen;
518         }
519         return 0;
520 }
521
522 int
523 libcfs_sock_write (cfs_socket_t *sock, void *buffer, int nob, int timeout)
524 {
525         size_t          sndlen;
526         int             rc;
527         cfs_duration_t  to = cfs_time_seconds(timeout);
528         cfs_time_t      then;
529         struct timeval  tv;
530
531         LASSERT(nob > 0);
532
533         for (;;) {
534                 struct iovec  iov = {
535                         .iov_base = buffer,
536                         .iov_len  = nob
537                 };
538                 struct  msghdr  msg = {
539                         .msg_name       = NULL,
540                         .msg_namelen    = 0,
541                         .msg_iov        = &iov,
542                         .msg_iovlen     = 1,
543                         .msg_control    = NULL,
544                         .msg_controllen = 0,
545                         .msg_flags      = (timeout == 0) ? MSG_DONTWAIT : 0,
546                 };
547
548                 if (timeout != 0) {
549                         cfs_duration_usec(to, &tv);
550                         rc = -sock_setsockopt(C2B_SOCK(sock), SOL_SOCKET, SO_SNDTIMEO,
551                                               &tv, sizeof(tv));
552                         if (rc != 0) {
553                                 CERROR("Can't set socket send timeout "
554                                        "%ld.%06d: %d\n",
555                                        (long)tv.tv_sec, (int)tv.tv_usec, rc);
556                                 return rc;
557                         }
558                 }
559
560                 then = cfs_time_current();
561                 rc = -sock_send(C2B_SOCK(sock), &msg, 
562                                 ((timeout == 0) ? MSG_DONTWAIT : 0), &sndlen);
563                 to -= cfs_time_current() - then;
564
565                 if (rc != 0 && rc != -EWOULDBLOCK)
566                         return rc;
567                 if (sndlen == nob)
568                         return 0;
569
570                 if (to <= 0)
571                         return -EAGAIN;
572                 buffer = ((char *)buffer) + sndlen;
573                 nob -= sndlen;
574         }
575         return 0;
576
577 }
578
579 int
580 libcfs_sock_getaddr (cfs_socket_t *sock, int remote, __u32 *ip, int *port)
581 {
582         struct sockaddr_in sin;
583         int                rc;
584
585         if (remote != 0) 
586                 /* Get remote address */
587                 rc = -sock_getpeername(C2B_SOCK(sock), (struct sockaddr *)&sin, sizeof(sin));
588         else 
589                 /* Get local address */
590                 rc = -sock_getsockname(C2B_SOCK(sock), (struct sockaddr *)&sin, sizeof(sin));
591         if (rc != 0) {
592                 CERROR ("Error %d getting sock %s IP/port\n",
593                          rc, remote ? "peer" : "local");
594                 return rc;
595         }
596
597         if (ip != NULL)
598                 *ip = ntohl (sin.sin_addr.s_addr);
599
600         if (port != NULL)
601                 *port = ntohs (sin.sin_port);
602         return 0;
603 }
604
605 int
606 libcfs_sock_setbuf (cfs_socket_t *sock, int txbufsize, int rxbufsize)
607 {
608         int                 option;
609         int                 rc;
610         
611         if (txbufsize != 0) {
612                 option = txbufsize;
613                 rc = -sock_setsockopt(C2B_SOCK(sock), SOL_SOCKET, SO_SNDBUF,
614                                      (char *)&option, sizeof (option));
615                 if (rc != 0) {
616                         CERROR ("Can't set send buffer %d: %d\n",
617                                 option, rc);
618                         return (rc);
619                 } 
620         } 
621         
622         if (rxbufsize != 0) {
623                 option = rxbufsize;
624                 rc = -sock_setsockopt (C2B_SOCK(sock), SOL_SOCKET, SO_RCVBUF,
625                                       (char *)&option, sizeof (option));
626                 if (rc != 0) {
627                         CERROR ("Can't set receive buffer %d: %d\n",
628                                 option, rc);
629                         return (rc);
630                 }
631         }
632         return 0;
633 }
634
635 int
636 libcfs_sock_getbuf (cfs_socket_t *sock, int *txbufsize, int *rxbufsize)
637 {
638         int                 option;
639         int                 optlen;
640         int                 rc; 
641         
642         if (txbufsize != NULL) {
643                 optlen = sizeof(option);
644                 rc = -sock_getsockopt(C2B_SOCK(sock), SOL_SOCKET, SO_SNDBUF,
645                                 (char *)&option, &optlen);
646                 if (rc != 0) {
647                         CERROR ("Can't get send buffer size: %d\n", rc);
648                         return (rc);
649                 }
650                 *txbufsize = option;
651         } 
652         
653         if (rxbufsize != NULL) {
654                 optlen = sizeof(option);
655                 rc = -sock_getsockopt (C2B_SOCK(sock), SOL_SOCKET, SO_RCVBUF,
656                                 (char *)&option, &optlen);
657                 if (rc != 0) {
658                         CERROR ("Can't get receive buffer size: %d\n", rc);
659                         return (rc);
660                 }
661                 *rxbufsize = option;
662         }
663         return 0;
664 }
665
666 void
667 libcfs_sock_release (cfs_socket_t *sock)
668 {
669         if (C2B_SOCK(sock) != NULL) {
670                 sock_shutdown(C2B_SOCK(sock), 2);
671                 sock_close(C2B_SOCK(sock));
672         }
673         FREE(sock, M_TEMP);
674 }
675
676 int
677 libcfs_sock_connect (cfs_socket_t **sockp, int *fatal,
678                      __u32 local_ip, int local_port,
679                      __u32 peer_ip, int peer_port)
680 {
681         cfs_socket_t       *sock;
682         struct sockaddr_in  srvaddr;
683         int                 rc; 
684         
685         rc = libcfs_sock_create(&sock, fatal, local_ip, local_port);
686         if (rc != 0)
687                 return rc;
688
689         bzero(&srvaddr, sizeof(srvaddr));
690         srvaddr.sin_len = sizeof(struct sockaddr_in);
691         srvaddr.sin_family = AF_INET;
692         srvaddr.sin_port = htons(peer_port);
693         srvaddr.sin_addr.s_addr = htonl(peer_ip);
694
695         rc = -sock_connect(C2B_SOCK(sock), (struct sockaddr *)&srvaddr, 0);
696         if (rc == 0) {
697                 *sockp = sock;
698                 return 0;
699         }
700
701         *fatal = !(rc == -EADDRNOTAVAIL || rc == -EADDRINUSE);
702         CDEBUG_LIMIT(*fatal ? D_NETERROR : D_NET,
703                "Error %d connecting %u.%u.%u.%u/%d -> %u.%u.%u.%u/%d\n", rc,
704                HIPQUAD(local_ip), local_port, HIPQUAD(peer_ip), peer_port);
705
706         libcfs_sock_release(sock);
707         return rc;
708 }
709
710 #else   /* !__DARWIN8__ */
711
712 /*
713  * To use bigger buffer for socket:
714  * 1. Increase nmbclusters (Cannot increased by sysctl because it's ready only, so
715  *    we must patch kernel).
716  * 2. Increase net.inet.tcp.reass.maxsegments
717  * 3. Increase net.inet.tcp.sendspace
718  * 4. Increase net.inet.tcp.recvspace
719  * 5. Increase kern.ipc.maxsockbuf
720  */
721 #define KSOCK_MAX_BUF        (1152*1024)
722
723 int
724 libcfs_ipif_query (char *name, int *up, __u32 *ip, __u32 *mask)
725 {
726         struct socket      *so;
727         struct ifreq       ifr;
728         int                nob;
729         int                rc;
730         __u32              val;
731         CFS_DECL_FUNNEL_DATA;
732
733         CFS_NET_IN;
734         rc = socreate(PF_INET, &so, SOCK_STREAM, 0);
735         CFS_NET_EX;
736         if (rc != 0) {
737                 CERROR ("Can't create socket: %d\n", rc);
738                 return (-rc);
739         }
740         nob = strnlen(name, IFNAMSIZ);
741         if (nob == IFNAMSIZ) {
742                 CERROR("Interface name %s too long\n", name);
743                 rc = -EINVAL;
744                 goto out;
745         }
746
747         CLASSERT (sizeof(ifr.ifr_name) >= IFNAMSIZ);
748         strcpy(ifr.ifr_name, name);
749         CFS_NET_IN;
750         rc = ifioctl(so, SIOCGIFFLAGS, (caddr_t)&ifr, current_proc());
751         CFS_NET_EX;
752
753         if (rc != 0) {
754                 CERROR("Can't get flags for interface %s\n", name);
755                 goto out;
756         }
757         if ((ifr.ifr_flags & IFF_UP) == 0) {
758                 CDEBUG(D_NET, "Interface %s down\n", name);
759                 *up = 0;
760                 *ip = *mask = 0;
761                 goto out;
762         }
763        
764         *up = 1;
765         strcpy(ifr.ifr_name, name);
766         *((struct sockaddr_in *)&ifr.ifr_addr) = blank_sin();
767         CFS_NET_IN;
768         rc = ifioctl(so, SIOCGIFADDR, (caddr_t)&ifr, current_proc());
769         CFS_NET_EX;
770
771         if (rc != 0) {
772                 CERROR("Can't get IP address for interface %s\n", name);
773                 goto out;
774         }
775
776         val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
777         *ip = ntohl(val);
778
779         strcpy(ifr.ifr_name, name);
780         *((struct sockaddr_in *)&ifr.ifr_addr) = blank_sin();
781         CFS_NET_IN;
782         rc = ifioctl(so, SIOCGIFNETMASK, (caddr_t)&ifr, current_proc());
783         CFS_NET_EX;
784
785         if (rc != 0) {
786                 CERROR("Can't get netmask for interface %s\n", name);
787                 goto out;
788         }
789
790         val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
791         *mask = ntohl(val);
792 out:
793         CFS_NET_IN;
794         soclose(so);
795         CFS_NET_EX;
796         return -rc;
797 }
798
799 int
800 libcfs_ipif_enumerate (char ***namesp)
801 {
802         /* Allocate and fill in 'names', returning # interfaces/error */
803         char           **names;
804         int             toobig;
805         int             nalloc;
806         int             nfound;
807         struct socket  *so;
808         struct ifreq   *ifr;
809         struct ifconf   ifc;
810         int             rc;
811         int             nob;
812         int             i;
813         CFS_DECL_FUNNEL_DATA;
814
815         CFS_NET_IN;
816         rc = socreate(PF_INET, &so, SOCK_STREAM, 0);
817         CFS_NET_EX;
818         if (rc != 0) {
819                 CERROR ("Can't create socket: %d\n", rc);
820                 return (-rc);
821         }
822
823         nalloc = 16;    /* first guess at max interfaces */
824         toobig = 0;
825         for (;;) {
826                 if (nalloc * sizeof(*ifr) > CFS_PAGE_SIZE) {
827                         toobig = 1;
828                         nalloc = CFS_PAGE_SIZE/sizeof(*ifr);
829                         CWARN("Too many interfaces: only enumerating first %d\n",
830                               nalloc);
831                 }
832
833                 LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr));
834                 if (ifr == NULL) {
835                         CERROR ("ENOMEM enumerating up to %d interfaces\n", nalloc);
836                                 rc = -ENOMEM;
837                         goto out0;
838                 }
839                                 
840                 ifc.ifc_buf = (char *)ifr;
841                 ifc.ifc_len = nalloc * sizeof(*ifr);
842                                         
843                 CFS_NET_IN;
844                 rc = -ifioctl(so, SIOCGIFCONF, (caddr_t)&ifc, current_proc());
845                 CFS_NET_EX;
846                                 
847                 if (rc < 0) {
848                         CERROR ("Error %d enumerating interfaces\n", rc);
849                         goto out1;
850                 }
851
852                 nfound = ifc.ifc_len/sizeof(*ifr);
853                 LASSERT (nfound <= nalloc);
854
855                 if (nfound < nalloc || toobig)
856                         break;
857
858                 LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
859                 nalloc *= 2;
860         }
861         if (nfound == 0)
862                 goto out1;
863
864         LIBCFS_ALLOC(names, nfound * sizeof(*names));
865         if (names == NULL) {
866                 rc = -ENOMEM;
867                 goto out1;
868         }
869         /* NULL out all names[i] */
870         memset (names, 0, nfound * sizeof(*names));
871
872         for (i = 0; i < nfound; i++) {
873
874                 nob = strnlen (ifr[i].ifr_name, IFNAMSIZ);
875                 if (nob == IFNAMSIZ) {
876                         /* no space for terminating NULL */
877                         CERROR("interface name %.*s too long (%d max)\n",
878                                nob, ifr[i].ifr_name, IFNAMSIZ);
879                         rc = -ENAMETOOLONG;
880                         goto out2;
881                 }
882
883                 LIBCFS_ALLOC(names[i], IFNAMSIZ);
884                 if (names[i] == NULL) {
885                         rc = -ENOMEM;
886                         goto out2;
887                 }
888
889                 memcpy(names[i], ifr[i].ifr_name, nob);
890                 names[i][nob] = 0;
891         }
892
893         *namesp = names;
894         rc = nfound;
895
896 out2:
897         if (rc < 0)
898                 libcfs_ipif_free_enumeration(names, nfound);
899 out1:
900         LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
901 out0:
902         CFS_NET_IN;
903         soclose(so);
904         CFS_NET_EX;
905         return rc;
906 }
907
908 static int
909 libcfs_sock_create (struct socket **sockp, int *fatal,
910                     __u32 local_ip, int local_port)
911 {
912         struct sockaddr_in  locaddr;
913         struct socket      *so;
914         struct sockopt      sopt;
915         int                 option;
916         int                 rc;
917         CFS_DECL_FUNNEL_DATA;
918
919         *fatal = 1;
920         CFS_NET_IN;
921         rc = socreate(PF_INET, &so, SOCK_STREAM, 0);
922         CFS_NET_EX;
923         if (rc != 0) {
924                 CERROR ("Can't create socket: %d\n", rc);
925                 return (-rc);
926         }
927         
928         bzero(&sopt, sizeof sopt);
929         option = 1;
930         sopt.sopt_level = SOL_SOCKET;
931         sopt.sopt_name = SO_REUSEADDR;
932         sopt.sopt_val = &option;
933         sopt.sopt_valsize = sizeof(option);
934         CFS_NET_IN;
935         rc = sosetopt(so, &sopt);
936         if (rc != 0) {
937                 CFS_NET_EX;
938                 CERROR ("Can't set sock reuse address: %d\n", rc);
939                 goto out;
940         }
941         /* can't specify a local port without a local IP */
942         LASSERT (local_ip == 0 || local_port != 0);
943
944         if (local_ip != 0 || local_port != 0) {
945                 bzero (&locaddr, sizeof (locaddr));
946                 locaddr.sin_len = sizeof(struct sockaddr_in);
947                 locaddr.sin_family = AF_INET;
948                 locaddr.sin_port = htons (local_port);
949                 locaddr.sin_addr.s_addr = (local_ip != 0) ? htonl(local_ip) :
950                                                             INADDR_ANY;
951
952                 rc = sobind(so, (struct sockaddr *)&locaddr);
953                 if (rc == EADDRINUSE) {
954                         CFS_NET_EX;
955                         CDEBUG(D_NET, "Port %d already in use\n", local_port);
956                         *fatal = 0;
957                         goto out;
958                 }
959                 if (rc != 0) {
960                         CFS_NET_EX;
961                         CERROR ("Can't bind to local IP Address %u.%u.%u.%u: %d\n",
962                         HIPQUAD(local_ip), rc);
963                         goto out;
964                 }
965         }
966         *sockp = so;
967         return 0;
968 out:
969         CFS_NET_IN;
970         soclose(so);
971         CFS_NET_EX;
972         return -rc;
973 }
974
975 int
976 libcfs_sock_listen (struct socket **sockp,
977                     __u32 local_ip, int local_port, int backlog)
978 {
979         int      fatal;
980         int      rc;
981         CFS_DECL_FUNNEL_DATA;
982
983         rc = libcfs_sock_create(sockp, &fatal, local_ip, local_port);
984         if (rc != 0) {
985                 if (!fatal)
986                         CERROR("Can't create socket: port %d already in use\n",
987                                local_port);
988                 return rc;
989         }
990         CFS_NET_IN;
991         rc = solisten(*sockp, backlog);
992         CFS_NET_EX;
993         if (rc == 0)
994                 return 0;
995         CERROR("Can't set listen backlog %d: %d\n", backlog, rc);
996         CFS_NET_IN;
997         soclose(*sockp);
998         CFS_NET_EX;
999         return -rc;
1000 }
1001
1002 int
1003 libcfs_sock_accept (struct socket **newsockp, struct socket *sock)
1004 {
1005         struct socket *so;
1006         struct sockaddr *sa;
1007         int error, s;
1008         CFS_DECL_FUNNEL_DATA;
1009
1010         CFS_NET_IN;
1011         s = splnet();
1012         if ((sock->so_options & SO_ACCEPTCONN) == 0) {
1013                 splx(s);
1014                 CFS_NET_EX;
1015                 return (-EINVAL);
1016         }
1017
1018         if ((sock->so_state & SS_NBIO) && sock->so_comp.tqh_first == NULL) {
1019                 splx(s);
1020                 CFS_NET_EX;
1021                 return (-EWOULDBLOCK);
1022         }
1023
1024         error = 0;
1025         while (TAILQ_EMPTY(&sock->so_comp) && sock->so_error == 0) {
1026                 if (sock->so_state & SS_CANTRCVMORE) {
1027                         sock->so_error = ECONNABORTED;
1028                         break;
1029                 }
1030                 error = tsleep((caddr_t)&sock->so_timeo, PSOCK | PCATCH,
1031                                 "accept", 0);
1032                 if (error) {
1033                         splx(s);
1034                         CFS_NET_EX;
1035                         return (-error);
1036                 }
1037         }
1038         if (sock->so_error) {
1039                 error = sock->so_error;
1040                 sock->so_error = 0;
1041                 splx(s);
1042                 CFS_NET_EX;
1043                 return (-error);
1044         }
1045
1046         /*
1047          * At this point we know that there is at least one connection
1048          * ready to be accepted. Remove it from the queue prior to
1049          * allocating the file descriptor for it since falloc() may
1050          * block allowing another process to accept the connection
1051          * instead.
1052          */
1053         so = TAILQ_FIRST(&sock->so_comp);
1054         TAILQ_REMOVE(&sock->so_comp, so, so_list);
1055         sock->so_qlen--;
1056
1057         so->so_state &= ~SS_COMP;
1058         so->so_head = NULL;
1059         sa = 0;
1060         (void) soaccept(so, &sa);
1061
1062         *newsockp = so;
1063         FREE(sa, M_SONAME);
1064         splx(s);
1065         CFS_NET_EX;
1066         return (-error);
1067 }
1068
1069 void
1070 libcfs_sock_abort_accept (struct socket *sock)
1071 {
1072         wakeup(&sock->so_timeo);
1073 }
1074
1075 /*
1076  * XXX Liang: timeout for write is not supported yet.
1077  */
1078 int
1079 libcfs_sock_write (struct socket *sock, void *buffer, int nob, int timeout)
1080 {
1081         int            rc;
1082         CFS_DECL_NET_DATA;
1083
1084         while (nob > 0) {
1085                 struct iovec  iov = {
1086                         .iov_base = buffer,
1087                         .iov_len  = nob
1088                 };
1089                 struct  uio suio = {
1090                         .uio_iov        = &iov,
1091                         .uio_iovcnt     = 1,
1092                         .uio_offset     = 0,
1093                         .uio_resid      = nob,
1094                         .uio_segflg     = UIO_SYSSPACE,
1095                         .uio_rw         = UIO_WRITE,
1096                         .uio_procp      = NULL
1097                 };
1098                                 
1099                 CFS_NET_IN;
1100                 rc = sosend(sock, NULL, &suio, (struct mbuf *)0, (struct mbuf *)0, 0);
1101                 CFS_NET_EX;
1102                                 
1103                 if (rc != 0) {
1104                         if ( suio.uio_resid != nob && ( rc == ERESTART || rc == EINTR ||\
1105                              rc == EWOULDBLOCK))
1106                         rc = 0;
1107                         if ( rc != 0 )
1108                                 return -rc;
1109                         rc = nob - suio.uio_resid;
1110                         buffer = ((char *)buffer) + rc;
1111                         nob = suio.uio_resid;
1112                         continue;
1113                 }
1114                 break;
1115         }
1116         return (0);
1117 }
1118
1119 /*
1120  * XXX Liang: timeout for read is not supported yet.
1121  */
1122 int
1123 libcfs_sock_read (struct socket *sock, void *buffer, int nob, int timeout)
1124 {
1125         int            rc;
1126         CFS_DECL_NET_DATA;
1127
1128         while (nob > 0) {
1129                 struct iovec  iov = {
1130                         .iov_base = buffer,
1131                         .iov_len  = nob
1132                 };
1133                 struct uio  ruio = {
1134                         .uio_iov        = &iov,
1135                         .uio_iovcnt     = 1,
1136                         .uio_offset     = 0,
1137                         .uio_resid      = nob,
1138                         .uio_segflg     = UIO_SYSSPACE,
1139                         .uio_rw         = UIO_READ,
1140                         .uio_procp      = NULL
1141                 };
1142                 
1143                 CFS_NET_IN;
1144                 rc = soreceive(sock, (struct sockaddr **)0, &ruio, (struct mbuf **)0, (struct mbuf **)0, (int *)0);
1145                 CFS_NET_EX;
1146                 
1147                 if (rc != 0) {
1148                         if ( ruio.uio_resid != nob && ( rc == ERESTART || rc == EINTR ||\
1149                                 rc == EWOULDBLOCK))
1150                                 rc = 0;
1151                         if (rc != 0)
1152                                 return -rc;
1153                         rc = nob - ruio.uio_resid;
1154                         buffer = ((char *)buffer) + rc;
1155                         nob = ruio.uio_resid;
1156                         continue;
1157                 }
1158                 break;
1159         }
1160         return (0);
1161 }
1162
1163 int
1164 libcfs_sock_setbuf (struct socket *sock, int txbufsize, int rxbufsize)
1165 {
1166         struct sockopt  sopt;
1167         int             rc = 0;
1168         int             option;
1169         CFS_DECL_NET_DATA;
1170
1171         bzero(&sopt, sizeof sopt);
1172         sopt.sopt_dir = SOPT_SET;
1173         sopt.sopt_level = SOL_SOCKET;
1174         sopt.sopt_val = &option;
1175         sopt.sopt_valsize = sizeof(option);
1176
1177         if (txbufsize != 0) {
1178                 option = txbufsize;
1179                 if (option > KSOCK_MAX_BUF)
1180                         option = KSOCK_MAX_BUF;
1181         
1182                 sopt.sopt_name = SO_SNDBUF;
1183                 CFS_NET_IN;
1184                 rc = sosetopt(sock, &sopt);
1185                 CFS_NET_EX;
1186                 if (rc != 0) {
1187                         CERROR ("Can't set send buffer %d: %d\n",
1188                                 option, rc);
1189                         
1190                         return -rc;
1191                 }
1192         }
1193                 
1194         if (rxbufsize != 0) {
1195                 option = rxbufsize;
1196                 sopt.sopt_name = SO_RCVBUF;
1197                 CFS_NET_IN;
1198                 rc = sosetopt(sock, &sopt);
1199                 CFS_NET_EX;
1200                 if (rc != 0) {
1201                         CERROR ("Can't set receive buffer %d: %d\n",
1202                                 option, rc);
1203                         return -rc;
1204                 }
1205         }
1206         return 0;
1207 }
1208
1209 int
1210 libcfs_sock_getaddr (struct socket *sock, int remote, __u32 *ip, int *port)
1211 {
1212         struct sockaddr_in *sin;
1213         struct sockaddr    *sa = NULL;
1214         int                rc;
1215         CFS_DECL_NET_DATA;
1216
1217         if (remote != 0) {
1218                 CFS_NET_IN;
1219                 rc = sock->so_proto->pr_usrreqs->pru_peeraddr(sock, &sa);
1220                 CFS_NET_EX;
1221
1222                 if (rc != 0) {
1223                         if (sa) FREE(sa, M_SONAME);
1224                         CERROR ("Error %d getting sock peer IP\n", rc);
1225                         return -rc;
1226                 }
1227         } else {
1228                 CFS_NET_IN;
1229                 rc = sock->so_proto->pr_usrreqs->pru_sockaddr(sock, &sa);
1230                 CFS_NET_EX;
1231                 if (rc != 0) {
1232                         if (sa) FREE(sa, M_SONAME);
1233                         CERROR ("Error %d getting sock local IP\n", rc);
1234                         return -rc;
1235                 }
1236         }
1237         if (sa != NULL) {
1238                 sin = (struct sockaddr_in *)sa;
1239                 if (ip != NULL)
1240                         *ip = ntohl (sin->sin_addr.s_addr);
1241                 if (port != NULL)
1242                         *port = ntohs (sin->sin_port);
1243                 if (sa) 
1244                         FREE(sa, M_SONAME);
1245         }
1246         return 0;
1247 }
1248
1249 int
1250 libcfs_sock_getbuf (struct socket *sock, int *txbufsize, int *rxbufsize)
1251 {
1252         struct sockopt  sopt;
1253         int rc;
1254         CFS_DECL_NET_DATA;
1255
1256         bzero(&sopt, sizeof sopt);
1257         sopt.sopt_dir = SOPT_GET;
1258         sopt.sopt_level = SOL_SOCKET;
1259
1260         if (txbufsize != NULL) {
1261                 sopt.sopt_val = txbufsize;
1262                 sopt.sopt_valsize = sizeof(*txbufsize);
1263                 sopt.sopt_name = SO_SNDBUF;
1264                 CFS_NET_IN;
1265                 rc = sogetopt(sock, &sopt);
1266                 CFS_NET_EX;
1267                 if (rc != 0) {
1268                         CERROR ("Can't get send buffer size: %d\n", rc);
1269                         return -rc;
1270                 }
1271         }
1272
1273         if (rxbufsize != NULL) {
1274                 sopt.sopt_val = rxbufsize;
1275                 sopt.sopt_valsize = sizeof(*rxbufsize);
1276                 sopt.sopt_name = SO_RCVBUF;
1277                 CFS_NET_IN;
1278                 rc = sogetopt(sock, &sopt);
1279                 CFS_NET_EX;
1280                 if (rc != 0) {
1281                         CERROR ("Can't get receive buffer size: %d\n", rc);
1282                         return -rc;
1283                 }
1284         }
1285         return 0;
1286 }
1287
1288 int
1289 libcfs_sock_connect (struct socket **sockp, int *fatal,
1290                      __u32 local_ip, int local_port,
1291                      __u32 peer_ip, int peer_port)
1292 {
1293         struct sockaddr_in  srvaddr;
1294         struct socket      *so;
1295         int                 s;
1296         int                 rc; 
1297         CFS_DECL_FUNNEL_DATA;
1298         
1299         rc = libcfs_sock_create(sockp, fatal, local_ip, local_port);
1300         if (rc != 0)
1301                 return rc;
1302         so = *sockp;
1303         bzero(&srvaddr, sizeof(srvaddr));
1304         srvaddr.sin_len = sizeof(struct sockaddr_in);
1305         srvaddr.sin_family = AF_INET;
1306         srvaddr.sin_port = htons (peer_port);
1307         srvaddr.sin_addr.s_addr = htonl (peer_ip);
1308
1309         CFS_NET_IN;
1310         rc = soconnect(so, (struct sockaddr *)&srvaddr);
1311         if (rc != 0) {
1312                 CFS_NET_EX;
1313                 if (rc != EADDRNOTAVAIL && rc != EADDRINUSE)
1314                         CNETERR("Error %d connecting %u.%u.%u.%u/%d -> %u.%u.%u.%u/%d\n", rc,
1315                                HIPQUAD(local_ip), local_port, HIPQUAD(peer_ip), peer_port);
1316                 goto out;
1317         }
1318         s = splnet();
1319         while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
1320                 CDEBUG(D_NET, "ksocknal sleep for waiting auto_connect.\n");
1321                 (void) tsleep((caddr_t)&so->so_timeo, PSOCK, "ksocknal_conn", hz);
1322         }
1323         if ((rc = so->so_error) != 0) {
1324                 so->so_error = 0;
1325                 splx(s);
1326                 CFS_NET_EX;
1327                 CNETERR("Error %d connecting %u.%u.%u.%u/%d -> %u.%u.%u.%u/%d\n", rc,
1328                        HIPQUAD(local_ip), local_port, HIPQUAD(peer_ip), peer_port);
1329                 goto out;
1330         }
1331         LASSERT(so->so_state & SS_ISCONNECTED);
1332         splx(s);
1333         CFS_NET_EX;
1334         if (sockp)
1335                 *sockp = so;
1336         return (0);
1337 out:
1338         CFS_NET_IN;
1339         soshutdown(so, 2);
1340         soclose(so);
1341         CFS_NET_EX;
1342         return (-rc);
1343 }
1344
1345 void
1346 libcfs_sock_release (struct socket *sock)
1347 {
1348         CFS_DECL_FUNNEL_DATA;
1349         CFS_NET_IN;
1350         soshutdown(sock, 0);
1351         CFS_NET_EX;
1352 }
1353
1354 #endif