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