173 #include <sys/systm.h>
174 #include <sys/kstat.h>
175 #include <sys/t_lock.h>
176 #include <sys/ddi.h>
177 #include <sys/cmn_err.h>
178 #include <sys/time.h>
179 #include <sys/isa_defs.h>
180 #include <sys/callb.h>
181 #include <sys/sunddi.h>
182 #include <sys/atomic.h>
183 #include <sys/sdt.h>
184
185 #include <netinet/in.h>
186 #include <netinet/tcp.h>
187
188 #include <rpc/types.h>
189 #include <rpc/xdr.h>
190 #include <rpc/auth.h>
191 #include <rpc/clnt.h>
192 #include <rpc/rpc_msg.h>
193
194 #define COTS_DEFAULT_ALLOCSIZE 2048
195
196 #define WIRE_HDR_SIZE 20 /* serialized call header, sans proc number */
197 #define MSG_OFFSET 128 /* offset of call into the mblk */
198
199 const char *kinet_ntop6(uchar_t *, char *, size_t);
200
201 static int clnt_cots_ksettimers(CLIENT *, struct rpc_timers *,
202 struct rpc_timers *, int, void(*)(int, int, caddr_t), caddr_t, uint32_t);
203 static enum clnt_stat clnt_cots_kcallit(CLIENT *, rpcproc_t, xdrproc_t,
204 caddr_t, xdrproc_t, caddr_t, struct timeval);
205 static void clnt_cots_kabort(CLIENT *);
206 static void clnt_cots_kerror(CLIENT *, struct rpc_err *);
207 static bool_t clnt_cots_kfreeres(CLIENT *, xdrproc_t, caddr_t);
208 static void clnt_cots_kdestroy(CLIENT *);
209 static bool_t clnt_cots_kcontrol(CLIENT *, int, char *);
210
211
212 /* List of transports managed by the connection manager. */
364 XDR cku_inxdr; /* xdr routine for input */
365 char cku_rpchdr[WIRE_HDR_SIZE + 4];
366 /* pre-serialized rpc header */
367
368 uint_t cku_outbuflen; /* default output mblk length */
369 struct cred *cku_cred; /* credentials */
370 bool_t cku_nodelayonerr;
371 /* for CLSET_NODELAYONERR */
372 int cku_useresvport; /* Use reserved port */
373 struct rpc_cots_client *cku_stats; /* stats for zone */
374 } cku_private_t;
375
376 static struct cm_xprt *connmgr_wrapconnect(struct cm_xprt *,
377 const struct timeval *, struct netbuf *, int, struct netbuf *,
378 struct rpc_err *, bool_t, bool_t, cred_t *);
379
380 static bool_t connmgr_connect(struct cm_xprt *, queue_t *, struct netbuf *,
381 int, calllist_t *, int *, bool_t reconnect,
382 const struct timeval *, bool_t, cred_t *);
383
384 static bool_t connmgr_setopt(queue_t *, int, int, calllist_t *, cred_t *cr);
385 static void connmgr_sndrel(struct cm_xprt *);
386 static void connmgr_snddis(struct cm_xprt *);
387 static void connmgr_close(struct cm_xprt *);
388 static void connmgr_release(struct cm_xprt *);
389 static struct cm_xprt *connmgr_wrapget(struct netbuf *, const struct timeval *,
390 cku_private_t *);
391
392 static struct cm_xprt *connmgr_get(struct netbuf *, const struct timeval *,
393 struct netbuf *, int, struct netbuf *, struct rpc_err *, dev_t,
394 bool_t, int, cred_t *);
395
396 static void connmgr_cancelconn(struct cm_xprt *);
397 static enum clnt_stat connmgr_cwait(struct cm_xprt *, const struct timeval *,
398 bool_t);
399 static void connmgr_dis_and_wait(struct cm_xprt *);
400
401 static int clnt_dispatch_send(queue_t *, mblk_t *, calllist_t *, uint_t,
402 uint_t);
403
485 #define htop(h) ((cku_private_t *)((h)->cl_private))
486
487 /*
488 * Times to retry
489 */
490 #define REFRESHES 2 /* authentication refreshes */
491
492 /*
493 * The following is used to determine the global default behavior for
494 * COTS when binding to a local port.
495 *
496 * If the value is set to 1 the default will be to select a reserved
497 * (aka privileged) port, if the value is zero the default will be to
498 * use non-reserved ports. Users of kRPC may override this by using
499 * CLNT_CONTROL() and CLSET_BINDRESVPORT.
500 */
501 int clnt_cots_do_bindresvport = 1;
502
503 static zone_key_t zone_cots_key;
504
505 /*
506 * We need to do this after all kernel threads in the zone have exited.
507 */
508 /* ARGSUSED */
509 static void
510 clnt_zone_destroy(zoneid_t zoneid, void *unused)
511 {
512 struct cm_xprt **cmp;
513 struct cm_xprt *cm_entry;
514 struct cm_xprt *freelist = NULL;
515
516 mutex_enter(&connmgr_lock);
517 cmp = &cm_hd;
518 while ((cm_entry = *cmp) != NULL) {
519 if (cm_entry->x_zoneid == zoneid) {
520 *cmp = cm_entry->x_next;
521 cm_entry->x_next = freelist;
522 freelist = cm_entry;
523 } else {
524 cmp = &cm_entry->x_next;
525 }
2541 if (cm_entry->x_src.buf != NULL)
2542 kmem_free(cm_entry->x_src.buf, cm_entry->x_src.maxlen);
2543 kmem_free(cm_entry, sizeof (struct cm_xprt));
2544 }
2545
2546 /*
2547 * Called by KRPC after sending the call message to release the connection
2548 * it was using.
2549 */
2550 static void
2551 connmgr_release(struct cm_xprt *cm_entry)
2552 {
2553 mutex_enter(&cm_entry->x_lock);
2554 cm_entry->x_ref--;
2555 if (cm_entry->x_ref == 0)
2556 cv_signal(&cm_entry->x_cv);
2557 mutex_exit(&cm_entry->x_lock);
2558 }
2559
2560 /*
2561 * Given an open stream, connect to the remote. Returns true if connected,
2562 * false otherwise.
2563 */
2564 static bool_t
2565 connmgr_connect(
2566 struct cm_xprt *cm_entry,
2567 queue_t *wq,
2568 struct netbuf *addr,
2569 int addrfmly,
2570 calllist_t *e,
2571 int *tidu_ptr,
2572 bool_t reconnect,
2573 const struct timeval *waitp,
2574 bool_t nosignal,
2575 cred_t *cr)
2576 {
2577 mblk_t *mp;
2578 struct T_conn_req *tcr;
2579 struct T_info_ack *tinfo;
2580 int interrupted, error;
2592 if (mp == NULL) {
2593 /*
2594 * This is unfortunate, but we need to look up the stats for
2595 * this zone to increment the "memory allocation failed"
2596 * counter. curproc->p_zone is safe since we're initiating a
2597 * connection and not in some strange streams context.
2598 */
2599 struct rpcstat *rpcstat;
2600
2601 rpcstat = zone_getspecific(rpcstat_zone_key, rpc_zone());
2602 ASSERT(rpcstat != NULL);
2603
2604 RPCLOG0(1, "connmgr_connect: cannot alloc mp for "
2605 "sending conn request\n");
2606 COTSRCSTAT_INCR(rpcstat->rpc_cots_client, rcnomem);
2607 e->call_status = RPC_SYSTEMERROR;
2608 e->call_reason = ENOSR;
2609 return (FALSE);
2610 }
2611
2612 mp->b_datap->db_type = M_PROTO;
2613 tcr = (struct T_conn_req *)mp->b_rptr;
2614 bzero(tcr, sizeof (*tcr));
2615 tcr->PRIM_type = T_CONN_REQ;
2616 tcr->DEST_length = addr->len;
2617 tcr->DEST_offset = sizeof (struct T_conn_req);
2618 mp->b_wptr = mp->b_rptr + sizeof (*tcr);
2619
2620 bcopy(addr->buf, mp->b_wptr, tcr->DEST_length);
2621 mp->b_wptr += tcr->DEST_length;
2622
2623 RPCLOG(8, "connmgr_connect: sending conn request on queue "
2624 "%p", (void *)wq);
2625 RPCLOG(8, " call %p\n", (void *)wq);
2626 /*
2627 * We use the entry in the handle that is normally used for
2628 * waiting for RPC replies to wait for the connection accept.
2629 */
2630 if (clnt_dispatch_send(wq, mp, e, 0, 0) != RPC_SUCCESS) {
2631 DTRACE_PROBE(krpc__e__connmgr__connect__cantsend);
2747 }
2748
2749 cm_entry->x_ksp->ks_lock = &connmgr_lock;
2750 cm_entry->x_ksp->ks_private = cm_entry;
2751 cm_entry->x_ksp->ks_data_size = ((INET6_ADDRSTRLEN * sizeof (char))
2752 + sizeof (cm_kstat_template));
2753 cm_entry->x_ksp->ks_data = kmem_alloc(cm_entry->x_ksp->ks_data_size,
2754 KM_SLEEP);
2755 bcopy(&cm_kstat_template, cm_entry->x_ksp->ks_data,
2756 cm_entry->x_ksp->ks_data_size);
2757 ((struct cm_kstat_xprt *)(cm_entry->x_ksp->ks_data))->
2758 x_server.value.str.addr.ptr =
2759 kmem_alloc(INET6_ADDRSTRLEN, KM_SLEEP);
2760
2761 cm_entry->x_ksp->ks_update = conn_kstat_update;
2762 kstat_install(cm_entry->x_ksp);
2763 return (TRUE);
2764 }
2765
2766 /*
2767 * Called by connmgr_connect to set an option on the new stream.
2768 */
2769 static bool_t
2770 connmgr_setopt(queue_t *wq, int level, int name, calllist_t *e, cred_t *cr)
2771 {
2772 mblk_t *mp;
2773 struct opthdr *opt;
2774 struct T_optmgmt_req *tor;
2775 struct timeval waitp;
2776 int error;
2777
2778 mp = allocb_cred(sizeof (struct T_optmgmt_req) +
2779 sizeof (struct opthdr) + sizeof (int), cr, NOPID);
2780 if (mp == NULL) {
2781 RPCLOG0(1, "connmgr_setopt: cannot alloc mp for option "
2782 "request\n");
2783 return (FALSE);
2784 }
2785
2786 mp->b_datap->db_type = M_PROTO;
2787 tor = (struct T_optmgmt_req *)(mp->b_rptr);
2788 tor->PRIM_type = T_SVR4_OPTMGMT_REQ;
2789 tor->MGMT_flags = T_NEGOTIATE;
2790 tor->OPT_length = sizeof (struct opthdr) + sizeof (int);
2791 tor->OPT_offset = sizeof (struct T_optmgmt_req);
2792
2793 opt = (struct opthdr *)(mp->b_rptr + sizeof (struct T_optmgmt_req));
2794 opt->level = level;
2795 opt->name = name;
2796 opt->len = sizeof (int);
2797 *(int *)((char *)opt + sizeof (*opt)) = 1;
2798 mp->b_wptr += sizeof (struct T_optmgmt_req) + sizeof (struct opthdr) +
2799 sizeof (int);
2800
2801 /*
2802 * We will use this connection regardless
2803 * of whether or not the option is settable.
2804 */
2805 if (clnt_dispatch_send(wq, mp, e, 0, 0) != RPC_SUCCESS) {
2806 DTRACE_PROBE(krpc__e__connmgr__setopt__cantsend);
2807 freemsg(mp);
2808 return (FALSE);
2809 }
2810
2811 mutex_enter(&clnt_pending_lock);
2812
2813 waitp.tv_sec = clnt_cots_min_conntout;
2814 waitp.tv_usec = 0;
2815 error = waitforack(e, T_OPTMGMT_ACK, &waitp, 1);
2816
2817 if (e->call_prev)
2818 e->call_prev->call_next = e->call_next;
2819 else
2820 clnt_pending = e->call_next;
2821 if (e->call_next)
2822 e->call_next->call_prev = e->call_prev;
2823 mutex_exit(&clnt_pending_lock);
2824
2825 if (e->call_reply != NULL) {
2826 freemsg(e->call_reply);
2827 e->call_reply = NULL;
2828 }
2829
2830 if (e->call_status != RPC_SUCCESS || error != 0) {
2831 RPCLOG(1, "connmgr_setopt: can't set option: %d\n", name);
2832 return (FALSE);
2833 }
2834 RPCLOG(8, "connmgr_setopt: successfully set option: %d\n", name);
2835 return (TRUE);
2836 }
2837
2838 #ifdef DEBUG
2839
2840 /*
2841 * This is a knob to let us force code coverage in allocation failure
2842 * case.
2843 */
2844 static int connmgr_failsnd;
2845 #define CONN_SND_ALLOC(Size, Pri) \
2846 ((connmgr_failsnd-- > 0) ? NULL : allocb(Size, Pri))
2847
2848 #else
2849
2850 #define CONN_SND_ALLOC(Size, Pri) allocb(Size, Pri)
2851
2852 #endif
2853
2854 /*
2855 * Sends an orderly release on the specified queue.
2856 * Entered with connmgr_lock. Exited without connmgr_lock
2857 */
|
173 #include <sys/systm.h>
174 #include <sys/kstat.h>
175 #include <sys/t_lock.h>
176 #include <sys/ddi.h>
177 #include <sys/cmn_err.h>
178 #include <sys/time.h>
179 #include <sys/isa_defs.h>
180 #include <sys/callb.h>
181 #include <sys/sunddi.h>
182 #include <sys/atomic.h>
183 #include <sys/sdt.h>
184
185 #include <netinet/in.h>
186 #include <netinet/tcp.h>
187
188 #include <rpc/types.h>
189 #include <rpc/xdr.h>
190 #include <rpc/auth.h>
191 #include <rpc/clnt.h>
192 #include <rpc/rpc_msg.h>
193 #include <nfs/nfs.h>
194
195 #define COTS_DEFAULT_ALLOCSIZE 2048
196
197 #define WIRE_HDR_SIZE 20 /* serialized call header, sans proc number */
198 #define MSG_OFFSET 128 /* offset of call into the mblk */
199
200 const char *kinet_ntop6(uchar_t *, char *, size_t);
201
202 static int clnt_cots_ksettimers(CLIENT *, struct rpc_timers *,
203 struct rpc_timers *, int, void(*)(int, int, caddr_t), caddr_t, uint32_t);
204 static enum clnt_stat clnt_cots_kcallit(CLIENT *, rpcproc_t, xdrproc_t,
205 caddr_t, xdrproc_t, caddr_t, struct timeval);
206 static void clnt_cots_kabort(CLIENT *);
207 static void clnt_cots_kerror(CLIENT *, struct rpc_err *);
208 static bool_t clnt_cots_kfreeres(CLIENT *, xdrproc_t, caddr_t);
209 static void clnt_cots_kdestroy(CLIENT *);
210 static bool_t clnt_cots_kcontrol(CLIENT *, int, char *);
211
212
213 /* List of transports managed by the connection manager. */
365 XDR cku_inxdr; /* xdr routine for input */
366 char cku_rpchdr[WIRE_HDR_SIZE + 4];
367 /* pre-serialized rpc header */
368
369 uint_t cku_outbuflen; /* default output mblk length */
370 struct cred *cku_cred; /* credentials */
371 bool_t cku_nodelayonerr;
372 /* for CLSET_NODELAYONERR */
373 int cku_useresvport; /* Use reserved port */
374 struct rpc_cots_client *cku_stats; /* stats for zone */
375 } cku_private_t;
376
377 static struct cm_xprt *connmgr_wrapconnect(struct cm_xprt *,
378 const struct timeval *, struct netbuf *, int, struct netbuf *,
379 struct rpc_err *, bool_t, bool_t, cred_t *);
380
381 static bool_t connmgr_connect(struct cm_xprt *, queue_t *, struct netbuf *,
382 int, calllist_t *, int *, bool_t reconnect,
383 const struct timeval *, bool_t, cred_t *);
384
385 static bool_t connmgr_getopt_int(queue_t *wq, int level, int name, int *val,
386 calllist_t *e, cred_t *cr);
387 static bool_t connmgr_setopt_int(queue_t *, int, int, int,
388 calllist_t *, cred_t *cr);
389 static bool_t connmgr_setopt(queue_t *, int, int, calllist_t *, cred_t *cr);
390 static void connmgr_sndrel(struct cm_xprt *);
391 static void connmgr_snddis(struct cm_xprt *);
392 static void connmgr_close(struct cm_xprt *);
393 static void connmgr_release(struct cm_xprt *);
394 static struct cm_xprt *connmgr_wrapget(struct netbuf *, const struct timeval *,
395 cku_private_t *);
396
397 static struct cm_xprt *connmgr_get(struct netbuf *, const struct timeval *,
398 struct netbuf *, int, struct netbuf *, struct rpc_err *, dev_t,
399 bool_t, int, cred_t *);
400
401 static void connmgr_cancelconn(struct cm_xprt *);
402 static enum clnt_stat connmgr_cwait(struct cm_xprt *, const struct timeval *,
403 bool_t);
404 static void connmgr_dis_and_wait(struct cm_xprt *);
405
406 static int clnt_dispatch_send(queue_t *, mblk_t *, calllist_t *, uint_t,
407 uint_t);
408
490 #define htop(h) ((cku_private_t *)((h)->cl_private))
491
492 /*
493 * Times to retry
494 */
495 #define REFRESHES 2 /* authentication refreshes */
496
497 /*
498 * The following is used to determine the global default behavior for
499 * COTS when binding to a local port.
500 *
501 * If the value is set to 1 the default will be to select a reserved
502 * (aka privileged) port, if the value is zero the default will be to
503 * use non-reserved ports. Users of kRPC may override this by using
504 * CLNT_CONTROL() and CLSET_BINDRESVPORT.
505 */
506 int clnt_cots_do_bindresvport = 1;
507
508 static zone_key_t zone_cots_key;
509
510 #define TWO_GIGB 0x80000000
511 int nfsd_port = NFS_PORT;
512 /*
513 * Defaults TCP send and receive buffer size for NFS connections.
514 * These values can be tuned by /etc/default.
515 */
516 int nfs_send_bufsz = 1024*1024;
517 int nfs_recv_bufsz = 1024*1024;
518 /*
519 * To use system-wide default for TCP send and receive buffer size,
520 * use /etc/system to set nfs_default_bufsz to 1:
521 *
522 * set rpcmod:nfs_default_bufsz=1
523 */
524 int nfs_default_bufsz = 0;
525
526 /*
527 * We need to do this after all kernel threads in the zone have exited.
528 */
529 /* ARGSUSED */
530 static void
531 clnt_zone_destroy(zoneid_t zoneid, void *unused)
532 {
533 struct cm_xprt **cmp;
534 struct cm_xprt *cm_entry;
535 struct cm_xprt *freelist = NULL;
536
537 mutex_enter(&connmgr_lock);
538 cmp = &cm_hd;
539 while ((cm_entry = *cmp) != NULL) {
540 if (cm_entry->x_zoneid == zoneid) {
541 *cmp = cm_entry->x_next;
542 cm_entry->x_next = freelist;
543 freelist = cm_entry;
544 } else {
545 cmp = &cm_entry->x_next;
546 }
2562 if (cm_entry->x_src.buf != NULL)
2563 kmem_free(cm_entry->x_src.buf, cm_entry->x_src.maxlen);
2564 kmem_free(cm_entry, sizeof (struct cm_xprt));
2565 }
2566
2567 /*
2568 * Called by KRPC after sending the call message to release the connection
2569 * it was using.
2570 */
2571 static void
2572 connmgr_release(struct cm_xprt *cm_entry)
2573 {
2574 mutex_enter(&cm_entry->x_lock);
2575 cm_entry->x_ref--;
2576 if (cm_entry->x_ref == 0)
2577 cv_signal(&cm_entry->x_cv);
2578 mutex_exit(&cm_entry->x_lock);
2579 }
2580
2581 /*
2582 * Set TCP receive and xmit buffer size for NFS connections.
2583 */
2584 static bool_t
2585 connmgr_nfs_setbufsz(calllist_t *e, int addrfmly, struct netbuf *addr,
2586 queue_t *wq, cred_t *cr)
2587 {
2588 struct sockaddr_in *sa;
2589 int ok = FALSE;
2590 int val;
2591 uint32_t sbufsz, rbufsz;
2592
2593 if (nfs_default_bufsz ||
2594 (addrfmly != AF_INET && addrfmly != AF_INET6))
2595 return (FALSE);
2596
2597 sa = (struct sockaddr_in *)addr->buf;
2598 if (ntohs(sa->sin_port) != nfsd_port)
2599 return (FALSE);
2600 /*
2601 * For system with 2GB, or less, of physical memory set send
2602 * and receive buffer size to half of nfs_send_bufsz and
2603 * nfs_recv_bufsz respectively.
2604 */
2605 if (ptob(physmem) <= TWO_GIGB) {
2606 sbufsz = nfs_send_bufsz >> 1;
2607 rbufsz = nfs_recv_bufsz >> 1;
2608 } else {
2609 sbufsz = nfs_send_bufsz;
2610 rbufsz = nfs_recv_bufsz;
2611 }
2612 /*
2613 * Only set new buffer size if it's larger than the system
2614 * default buffer size. If smaller buffer size is needed
2615 * then use /etc/system to set nfs_default_bufsz to 1.
2616 */
2617 ok = connmgr_getopt_int(wq, SOL_SOCKET, SO_RCVBUF, &val, e, cr);
2618 if ((ok == TRUE) && (val < sbufsz)) {
2619 ok = connmgr_setopt_int(wq, SOL_SOCKET, SO_RCVBUF,
2620 sbufsz, e, cr);
2621 DTRACE_PROBE2(connmgr_nfs_rcvbufsz__setopt,
2622 int, ok, calllist_t *, e);
2623 }
2624
2625 ok = connmgr_getopt_int(wq, SOL_SOCKET, SO_SNDBUF, &val, e, cr);
2626 if ((ok == TRUE) && (val < rbufsz)) {
2627 ok = connmgr_setopt_int(wq, SOL_SOCKET, SO_SNDBUF,
2628 rbufsz, e, cr);
2629 DTRACE_PROBE2(connmgr_nfs_sndbufsz__setopt,
2630 int, ok, calllist_t *, e);
2631 }
2632 return (TRUE);
2633 }
2634
2635 /*
2636 * Given an open stream, connect to the remote. Returns true if connected,
2637 * false otherwise.
2638 */
2639 static bool_t
2640 connmgr_connect(
2641 struct cm_xprt *cm_entry,
2642 queue_t *wq,
2643 struct netbuf *addr,
2644 int addrfmly,
2645 calllist_t *e,
2646 int *tidu_ptr,
2647 bool_t reconnect,
2648 const struct timeval *waitp,
2649 bool_t nosignal,
2650 cred_t *cr)
2651 {
2652 mblk_t *mp;
2653 struct T_conn_req *tcr;
2654 struct T_info_ack *tinfo;
2655 int interrupted, error;
2667 if (mp == NULL) {
2668 /*
2669 * This is unfortunate, but we need to look up the stats for
2670 * this zone to increment the "memory allocation failed"
2671 * counter. curproc->p_zone is safe since we're initiating a
2672 * connection and not in some strange streams context.
2673 */
2674 struct rpcstat *rpcstat;
2675
2676 rpcstat = zone_getspecific(rpcstat_zone_key, rpc_zone());
2677 ASSERT(rpcstat != NULL);
2678
2679 RPCLOG0(1, "connmgr_connect: cannot alloc mp for "
2680 "sending conn request\n");
2681 COTSRCSTAT_INCR(rpcstat->rpc_cots_client, rcnomem);
2682 e->call_status = RPC_SYSTEMERROR;
2683 e->call_reason = ENOSR;
2684 return (FALSE);
2685 }
2686
2687 /* Set TCP buffer size for NFS connections if needed */
2688 (void) connmgr_nfs_setbufsz(e, addrfmly, addr, wq, cr);
2689
2690 mp->b_datap->db_type = M_PROTO;
2691 tcr = (struct T_conn_req *)mp->b_rptr;
2692 bzero(tcr, sizeof (*tcr));
2693 tcr->PRIM_type = T_CONN_REQ;
2694 tcr->DEST_length = addr->len;
2695 tcr->DEST_offset = sizeof (struct T_conn_req);
2696 mp->b_wptr = mp->b_rptr + sizeof (*tcr);
2697
2698 bcopy(addr->buf, mp->b_wptr, tcr->DEST_length);
2699 mp->b_wptr += tcr->DEST_length;
2700
2701 RPCLOG(8, "connmgr_connect: sending conn request on queue "
2702 "%p", (void *)wq);
2703 RPCLOG(8, " call %p\n", (void *)wq);
2704 /*
2705 * We use the entry in the handle that is normally used for
2706 * waiting for RPC replies to wait for the connection accept.
2707 */
2708 if (clnt_dispatch_send(wq, mp, e, 0, 0) != RPC_SUCCESS) {
2709 DTRACE_PROBE(krpc__e__connmgr__connect__cantsend);
2825 }
2826
2827 cm_entry->x_ksp->ks_lock = &connmgr_lock;
2828 cm_entry->x_ksp->ks_private = cm_entry;
2829 cm_entry->x_ksp->ks_data_size = ((INET6_ADDRSTRLEN * sizeof (char))
2830 + sizeof (cm_kstat_template));
2831 cm_entry->x_ksp->ks_data = kmem_alloc(cm_entry->x_ksp->ks_data_size,
2832 KM_SLEEP);
2833 bcopy(&cm_kstat_template, cm_entry->x_ksp->ks_data,
2834 cm_entry->x_ksp->ks_data_size);
2835 ((struct cm_kstat_xprt *)(cm_entry->x_ksp->ks_data))->
2836 x_server.value.str.addr.ptr =
2837 kmem_alloc(INET6_ADDRSTRLEN, KM_SLEEP);
2838
2839 cm_entry->x_ksp->ks_update = conn_kstat_update;
2840 kstat_install(cm_entry->x_ksp);
2841 return (TRUE);
2842 }
2843
2844 /*
2845 * Verify that the specified offset falls within the mblk and
2846 * that the resulting pointer is aligned.
2847 * Returns NULL if not.
2848 *
2849 * code from fs/sockfs/socksubr.c
2850 */
2851 static void *
2852 connmgr_opt_getoff(mblk_t *mp, t_uscalar_t offset,
2853 t_uscalar_t length, uint_t align_size)
2854 {
2855 uintptr_t ptr1, ptr2;
2856
2857 ASSERT(mp && mp->b_wptr >= mp->b_rptr);
2858 ptr1 = (uintptr_t)mp->b_rptr + offset;
2859 ptr2 = (uintptr_t)ptr1 + length;
2860 if (ptr1 < (uintptr_t)mp->b_rptr || ptr2 > (uintptr_t)mp->b_wptr) {
2861 return (NULL);
2862 }
2863 if ((ptr1 & (align_size - 1)) != 0) {
2864 return (NULL);
2865 }
2866 return ((void *)ptr1);
2867 }
2868
2869 static bool_t
2870 connmgr_getopt_int(queue_t *wq, int level, int name, int *val,
2871 calllist_t *e, cred_t *cr)
2872 {
2873 mblk_t *mp;
2874 struct opthdr *opt, *opt_res;
2875 struct T_optmgmt_req *tor;
2876 struct T_optmgmt_ack *opt_ack;
2877 struct timeval waitp;
2878 int error;
2879
2880 mp = allocb_cred(sizeof (struct T_optmgmt_req) +
2881 sizeof (struct opthdr) + sizeof (int), cr, NOPID);
2882 if (mp == NULL) {
2883 RPCLOG0(1, "connmgr_getopt: cannot alloc mp for option "
2884 "request\n");
2885 return (FALSE);
2886 }
2887
2888 mp->b_datap->db_type = M_PROTO;
2889 tor = (struct T_optmgmt_req *)(mp->b_rptr);
2890 tor->PRIM_type = T_SVR4_OPTMGMT_REQ;
2891 tor->MGMT_flags = T_CURRENT;
2892 tor->OPT_length = sizeof (struct opthdr) + sizeof (int);
2893 tor->OPT_offset = sizeof (struct T_optmgmt_req);
2894
2895 opt = (struct opthdr *)(mp->b_rptr + sizeof (struct T_optmgmt_req));
2896 opt->level = level;
2897 opt->name = name;
2898 opt->len = sizeof (int);
2899 mp->b_wptr += sizeof (struct T_optmgmt_req) + sizeof (struct opthdr) +
2900 sizeof (int);
2901
2902 /*
2903 * We will use this connection regardless
2904 * of whether or not the option is readable.
2905 */
2906 if (clnt_dispatch_send(wq, mp, e, 0, 0) != RPC_SUCCESS) {
2907 DTRACE_PROBE(krpc__e__connmgr__getopt__cantsend);
2908 freemsg(mp);
2909 return (FALSE);
2910 }
2911
2912 mutex_enter(&clnt_pending_lock);
2913
2914 waitp.tv_sec = clnt_cots_min_conntout;
2915 waitp.tv_usec = 0;
2916 error = waitforack(e, T_OPTMGMT_ACK, &waitp, 1);
2917
2918 if (e->call_prev)
2919 e->call_prev->call_next = e->call_next;
2920 else
2921 clnt_pending = e->call_next;
2922 if (e->call_next)
2923 e->call_next->call_prev = e->call_prev;
2924 mutex_exit(&clnt_pending_lock);
2925
2926 /* get reply message */
2927 mp = e->call_reply;
2928 e->call_reply = NULL;
2929
2930 if ((!mp) || (e->call_status != RPC_SUCCESS) || (error != 0)) {
2931
2932 DTRACE_PROBE4(connmgr_getopt__failed, int, name,
2933 int, e->call_status, int, error, mblk_t *, mp);
2934
2935 if (mp)
2936 freemsg(mp);
2937 return (FALSE);
2938 }
2939
2940 opt_ack = (struct T_optmgmt_ack *)mp->b_rptr;
2941 opt_res = (struct opthdr *)connmgr_opt_getoff(mp, opt_ack->OPT_offset,
2942 opt_ack->OPT_length, __TPI_ALIGN_SIZE);
2943
2944 if (!opt_res) {
2945 DTRACE_PROBE4(connmgr_getopt__optres, mblk_t *, mp, int, name,
2946 int, opt_ack->OPT_offset, int, opt_ack->OPT_length);
2947 freemsg(mp);
2948 return (FALSE);
2949 }
2950 *val = *(int *)&opt_res[1];
2951
2952 DTRACE_PROBE2(connmgr_getopt__ok, int, name, int, *val);
2953
2954 freemsg(mp);
2955 return (TRUE);
2956 }
2957
2958 /*
2959 * Called by connmgr_connect to set an option on the new stream.
2960 */
2961 static bool_t
2962 connmgr_setopt_int(queue_t *wq, int level, int name, int val,
2963 calllist_t *e, cred_t *cr)
2964 {
2965 mblk_t *mp;
2966 struct opthdr *opt;
2967 struct T_optmgmt_req *tor;
2968 struct timeval waitp;
2969 int error;
2970
2971 mp = allocb_cred(sizeof (struct T_optmgmt_req) +
2972 sizeof (struct opthdr) + sizeof (int), cr, NOPID);
2973 if (mp == NULL) {
2974 RPCLOG0(1, "connmgr_setopt: cannot alloc mp for option "
2975 "request\n");
2976 return (FALSE);
2977 }
2978
2979 mp->b_datap->db_type = M_PROTO;
2980 tor = (struct T_optmgmt_req *)(mp->b_rptr);
2981 tor->PRIM_type = T_SVR4_OPTMGMT_REQ;
2982 tor->MGMT_flags = T_NEGOTIATE;
2983 tor->OPT_length = sizeof (struct opthdr) + sizeof (int);
2984 tor->OPT_offset = sizeof (struct T_optmgmt_req);
2985
2986 opt = (struct opthdr *)(mp->b_rptr + sizeof (struct T_optmgmt_req));
2987 opt->level = level;
2988 opt->name = name;
2989 opt->len = sizeof (int);
2990 *(int *)((char *)opt + sizeof (*opt)) = val;
2991 mp->b_wptr += sizeof (struct T_optmgmt_req) + sizeof (struct opthdr) +
2992 sizeof (int);
2993
2994 /*
2995 * We will use this connection regardless
2996 * of whether or not the option is settable.
2997 */
2998 if (clnt_dispatch_send(wq, mp, e, 0, 0) != RPC_SUCCESS) {
2999 DTRACE_PROBE(krpc__e__connmgr__setopt__cantsend);
3000 freemsg(mp);
3001 return (FALSE);
3002 }
3003
3004 mutex_enter(&clnt_pending_lock);
3005
3006 waitp.tv_sec = clnt_cots_min_conntout;
3007 waitp.tv_usec = 0;
3008 error = waitforack(e, T_OPTMGMT_ACK, &waitp, 1);
3009
3010 if (e->call_prev)
3011 e->call_prev->call_next = e->call_next;
3012 else
3013 clnt_pending = e->call_next;
3014 if (e->call_next)
3015 e->call_next->call_prev = e->call_prev;
3016 mutex_exit(&clnt_pending_lock);
3017
3018 if (e->call_reply != NULL) {
3019 freemsg(e->call_reply);
3020 e->call_reply = NULL;
3021 }
3022
3023 if (e->call_status != RPC_SUCCESS || error != 0) {
3024 RPCLOG(1, "connmgr_setopt: can't set option: %d\n", name);
3025 return (FALSE);
3026 }
3027 RPCLOG(8, "connmgr_setopt: successfully set option: %d\n", name);
3028 return (TRUE);
3029 }
3030
3031 static bool_t
3032 connmgr_setopt(queue_t *wq, int level, int name, calllist_t *e, cred_t *cr)
3033 {
3034 return (connmgr_setopt_int(wq, level, name, 1, e, cr));
3035 }
3036
3037 #ifdef DEBUG
3038
3039 /*
3040 * This is a knob to let us force code coverage in allocation failure
3041 * case.
3042 */
3043 static int connmgr_failsnd;
3044 #define CONN_SND_ALLOC(Size, Pri) \
3045 ((connmgr_failsnd-- > 0) ? NULL : allocb(Size, Pri))
3046
3047 #else
3048
3049 #define CONN_SND_ALLOC(Size, Pri) allocb(Size, Pri)
3050
3051 #endif
3052
3053 /*
3054 * Sends an orderly release on the specified queue.
3055 * Entered with connmgr_lock. Exited without connmgr_lock
3056 */
|