root/usr/src/uts/common/inet/sockmods/sockmod_sdp.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#include <sys/sysmacros.h>
#include <sys/strsubr.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/modctl.h>
#include <sys/cmn_err.h>
#include <sys/vfs.h>
#include <inet/sdp_itf.h>
#include <fs/sockfs/sockcommon.h>
#include "socksdp.h"

struct sonode *socksdp_create(struct sockparams *, int, int, int,
    int, int, int *, cred_t *);
static void socksdp_destroy(struct sonode *);

static __smod_priv_t sosdp_priv = {
        socksdp_create,
        socksdp_destroy,
        NULL
};

static smod_reg_t sinfo = {
        SOCKMOD_VERSION,
        "socksdp",
        SOCK_UC_VERSION,
        SOCK_DC_VERSION,
        NULL,
        &sosdp_priv
};

/*
 * Module linkage information for the kernel
 */
static struct modlsockmod modlsockmod = {
        &mod_sockmodops, "SDP socket module", &sinfo
};

static struct modlinkage modlinkage = {
        MODREV_1,
        &modlsockmod,
        NULL
};

/*
 * Creates a sdp socket data structure.
 */
/* ARGSUSED */
struct sonode *
socksdp_create(struct sockparams *sp, int family, int type, int protocol,
                    int version, int sflags, int *errorp, cred_t *cr)
{
        struct sonode *so;
        int kmflags = (sflags & SOCKET_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP;

        dprint(4, ("Inside sosdp_create: domain:%d proto:%d type:%d",
            family, protocol, type));

        *errorp = 0;
        if (is_system_labeled()) {
                *errorp = EOPNOTSUPP;
                return (NULL);
        }

        if (version == SOV_STREAM) {
                *errorp = EINVAL;
                return (NULL);
        }

        /*
         * We only support one type of SDP socket.  Let sotpi_create()
         * handle all other cases, such as raw socket.
         */
        if (!(family == AF_INET || family == AF_INET6) ||
            !(type == SOCK_STREAM)) {
                *errorp = EINVAL;
                return (NULL);
        }

        so = kmem_cache_alloc(socket_cache, kmflags);
        if (so == NULL) {
                *errorp = ENOMEM;
                return (NULL);
        }

        sonode_init(so, sp, family, type, protocol, &sosdp_sonodeops);
        so->so_pollev |= SO_POLLEV_ALWAYS;

        dprint(2, ("sosdp_create: %p domain %d type %d\n", (void *)so, family,
            type));

        if (version == SOV_DEFAULT) {
                version = so_default_version;
        }
        so->so_version = (short)version;

        /*
         * set the default values to be INFPSZ
         * if a protocol desires it can change the value later
         */
        so->so_proto_props.sopp_rxhiwat = SOCKET_RECVHIWATER;
        so->so_proto_props.sopp_rxlowat = SOCKET_RECVLOWATER;
        so->so_proto_props.sopp_maxpsz = INFPSZ;
        so->so_proto_props.sopp_maxblk = INFPSZ;

        return (so);
}

static void
socksdp_destroy(struct sonode *so)
{
        ASSERT(so->so_ops == &sosdp_sonodeops);

        sosdp_fini(so, CRED());

        kmem_cache_free(socket_cache, so);
}

int
_init(void)
{
        return (mod_install(&modlinkage));
}

int
_fini(void)
{
        return (mod_remove(&modlinkage));
}

int
_info(struct modinfo *modinfop)
{
        return (mod_info(&modlinkage, modinfop));
}