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