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