4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 1990 Mentat Inc.
24 */
25
26 /*
27 * This file contains the interface control functions for IP.
28 */
29
30 #include <sys/types.h>
31 #include <sys/stream.h>
32 #include <sys/dlpi.h>
33 #include <sys/stropts.h>
34 #include <sys/strsun.h>
35 #include <sys/sysmacros.h>
36 #include <sys/strsubr.h>
37 #include <sys/strlog.h>
38 #include <sys/ddi.h>
39 #include <sys/sunddi.h>
40 #include <sys/cmn_err.h>
41 #include <sys/kstat.h>
42 #include <sys/debug.h>
43 #include <sys/zone.h>
8837 (flags & MOD_PROP_POSSIBLE) != MOD_PROP_POSSIBLE &&
8838 (flags & MOD_PROP_PERM) != MOD_PROP_PERM)
8839 return (B_FALSE);
8840 }
8841
8842 return (B_TRUE);
8843 }
8844
8845 /*
8846 * process the SIOC{SET|GET}PROP ioctl's
8847 */
8848 /* ARGSUSED */
8849 static void
8850 ip_sioctl_getsetprop(queue_t *q, mblk_t *mp)
8851 {
8852 struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
8853 mblk_t *mp1 = mp->b_cont;
8854 mod_ioc_prop_t *pioc;
8855 mod_prop_info_t *ptbl = NULL, *pinfo = NULL;
8856 ip_stack_t *ipst;
8857 icmp_stack_t *is;
8858 tcp_stack_t *tcps;
8859 sctp_stack_t *sctps;
8860 udp_stack_t *us;
8861 netstack_t *stack;
8862 void *cbarg;
8863 cred_t *cr;
8864 boolean_t set;
8865 int err;
8866
8867 ASSERT(q->q_next == NULL);
8868 ASSERT(CONN_Q(q));
8869
8870 if (!getset_ioctl_checks(mp)) {
8871 miocnak(q, mp, 0, EINVAL);
8872 return;
8873 }
8874 ipst = CONNQ_TO_IPST(q);
8875 stack = ipst->ips_netstack;
8876 pioc = (mod_ioc_prop_t *)mp1->b_rptr;
8877
8878 switch (pioc->mpr_proto) {
8879 case MOD_PROTO_IP:
8880 case MOD_PROTO_IPV4:
8881 case MOD_PROTO_IPV6:
8882 ptbl = ipst->ips_propinfo_tbl;
8883 cbarg = ipst;
8884 break;
8885 case MOD_PROTO_RAWIP:
8886 is = stack->netstack_icmp;
8887 ptbl = is->is_propinfo_tbl;
8888 cbarg = is;
8889 break;
8890 case MOD_PROTO_TCP:
8891 tcps = stack->netstack_tcp;
8892 ptbl = tcps->tcps_propinfo_tbl;
8893 cbarg = tcps;
8894 break;
8895 case MOD_PROTO_UDP:
8896 us = stack->netstack_udp;
8897 ptbl = us->us_propinfo_tbl;
8898 cbarg = us;
8899 break;
8900 case MOD_PROTO_SCTP:
8901 sctps = stack->netstack_sctp;
8902 ptbl = sctps->sctps_propinfo_tbl;
8903 cbarg = sctps;
8904 break;
8905 default:
8906 miocnak(q, mp, 0, EINVAL);
8907 return;
8908 }
8909
8910 /* search for given property in respective protocol propinfo table */
8911 for (pinfo = ptbl; pinfo->mpi_name != NULL; pinfo++) {
8912 if (strcmp(pinfo->mpi_name, pioc->mpr_name) == 0 &&
8913 pinfo->mpi_proto == pioc->mpr_proto)
8914 break;
8915 }
8916 if (pinfo->mpi_name == NULL) {
8917 miocnak(q, mp, 0, ENOENT);
8918 return;
8919 }
8920
8921 set = (iocp->ioc_cmd == SIOCSETPROP) ? B_TRUE : B_FALSE;
8922 if (set && pinfo->mpi_setf != NULL) {
8923 cr = msg_getcred(mp, NULL);
8924 if (cr == NULL)
8925 cr = iocp->ioc_cr;
8926 err = pinfo->mpi_setf(cbarg, cr, pinfo, pioc->mpr_ifname,
8927 pioc->mpr_val, pioc->mpr_flags);
8928 } else if (!set && pinfo->mpi_getf != NULL) {
8929 err = pinfo->mpi_getf(cbarg, pinfo, pioc->mpr_ifname,
8930 pioc->mpr_val, pioc->mpr_valsize, pioc->mpr_flags);
8931 } else {
8932 err = EPERM;
8933 }
8934
8935 if (err != 0) {
8936 miocnak(q, mp, 0, err);
8937 } else {
8938 if (set)
8939 miocack(q, mp, 0, 0);
8940 else /* For get, we need to return back the data */
8941 miocack(q, mp, iocp->ioc_count, 0);
8942 }
8943 }
8944
8945 /*
8946 * process the legacy ND_GET, ND_SET ioctl just for {ip|ip6}_forwarding
8947 * as several routing daemons have unfortunately used this 'unpublished'
8948 * but well-known ioctls.
8949 */
8950 /* ARGSUSED */
8951 static void
8952 ip_process_legacy_nddprop(queue_t *q, mblk_t *mp)
8953 {
8954 struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
8955 mblk_t *mp1 = mp->b_cont;
8956 char *pname, *pval, *buf;
8957 uint_t bufsize, proto;
8958 mod_prop_info_t *ptbl = NULL, *pinfo = NULL;
8959 ip_stack_t *ipst;
8960 int err = 0;
8961
8962 ASSERT(CONN_Q(q));
8963 ipst = CONNQ_TO_IPST(q);
8964
8965 if (iocp->ioc_count == 0 || mp1 == NULL) {
8966 miocnak(q, mp, 0, EINVAL);
8967 return;
8968 }
8969
8970 mp1->b_datap->db_lim[-1] = '\0'; /* Force null termination */
8971 pval = buf = pname = (char *)mp1->b_rptr;
8972 bufsize = MBLKL(mp1);
8973
8974 if (strcmp(pname, "ip_forwarding") == 0) {
8975 pname = "forwarding";
8976 proto = MOD_PROTO_IPV4;
8977 } else if (strcmp(pname, "ip6_forwarding") == 0) {
8978 pname = "forwarding";
8979 proto = MOD_PROTO_IPV6;
8980 } else {
8981 miocnak(q, mp, 0, EINVAL);
8982 return;
8983 }
8984
8985 ptbl = ipst->ips_propinfo_tbl;
8986 for (pinfo = ptbl; pinfo->mpi_name != NULL; pinfo++) {
8987 if (strcmp(pinfo->mpi_name, pname) == 0 &&
8988 pinfo->mpi_proto == proto)
8989 break;
8990 }
8991
8992 ASSERT(pinfo->mpi_name != NULL);
8993
8994 switch (iocp->ioc_cmd) {
8995 case ND_GET:
8996 if ((err = pinfo->mpi_getf(ipst, pinfo, NULL, buf, bufsize,
8997 0)) == 0) {
8998 miocack(q, mp, iocp->ioc_count, 0);
8999 return;
9000 }
9001 break;
9002 case ND_SET:
9003 /*
9004 * buffer will have property name and value in the following
9005 * format,
9006 * <property name>'\0'<property value>'\0', extract them;
9007 */
9008 while (*pval++)
9009 noop;
9010
9011 if (!*pval || pval >= (char *)mp1->b_wptr) {
9012 err = EINVAL;
9013 } else if ((err = pinfo->mpi_setf(ipst, NULL, pinfo, NULL,
9014 pval, 0)) == 0) {
9015 miocack(q, mp, 0, 0);
9016 return;
9017 }
9018 break;
9019 default:
9020 err = EINVAL;
9021 break;
9022 }
9023 miocnak(q, mp, 0, err);
9024 }
9025
9026 /*
9027 * Wrapper function for resuming deferred ioctl processing
9028 * Used for SIOCGDSTINFO, SIOCGIP6ADDRPOLICY, SIOCGMSFILTER,
9029 * SIOCSMSFILTER, SIOCGIPMSFILTER, and SIOCSIPMSFILTER currently.
9030 */
9031 /* ARGSUSED */
9032 void
9033 ip_sioctl_copyin_resume(ipsq_t *dummy_ipsq, queue_t *q, mblk_t *mp,
9034 void *dummy_arg)
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 1990 Mentat Inc.
24 * Copyright (c) 2013 by Delphix. All rights reserved.
25 */
26
27 /*
28 * This file contains the interface control functions for IP.
29 */
30
31 #include <sys/types.h>
32 #include <sys/stream.h>
33 #include <sys/dlpi.h>
34 #include <sys/stropts.h>
35 #include <sys/strsun.h>
36 #include <sys/sysmacros.h>
37 #include <sys/strsubr.h>
38 #include <sys/strlog.h>
39 #include <sys/ddi.h>
40 #include <sys/sunddi.h>
41 #include <sys/cmn_err.h>
42 #include <sys/kstat.h>
43 #include <sys/debug.h>
44 #include <sys/zone.h>
8838 (flags & MOD_PROP_POSSIBLE) != MOD_PROP_POSSIBLE &&
8839 (flags & MOD_PROP_PERM) != MOD_PROP_PERM)
8840 return (B_FALSE);
8841 }
8842
8843 return (B_TRUE);
8844 }
8845
8846 /*
8847 * process the SIOC{SET|GET}PROP ioctl's
8848 */
8849 /* ARGSUSED */
8850 static void
8851 ip_sioctl_getsetprop(queue_t *q, mblk_t *mp)
8852 {
8853 struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
8854 mblk_t *mp1 = mp->b_cont;
8855 mod_ioc_prop_t *pioc;
8856 mod_prop_info_t *ptbl = NULL, *pinfo = NULL;
8857 ip_stack_t *ipst;
8858 netstack_t *stack;
8859 cred_t *cr;
8860 boolean_t set;
8861 int err;
8862
8863 ASSERT(q->q_next == NULL);
8864 ASSERT(CONN_Q(q));
8865
8866 if (!getset_ioctl_checks(mp)) {
8867 miocnak(q, mp, 0, EINVAL);
8868 return;
8869 }
8870 ipst = CONNQ_TO_IPST(q);
8871 stack = ipst->ips_netstack;
8872 pioc = (mod_ioc_prop_t *)mp1->b_rptr;
8873
8874 switch (pioc->mpr_proto) {
8875 case MOD_PROTO_IP:
8876 case MOD_PROTO_IPV4:
8877 case MOD_PROTO_IPV6:
8878 ptbl = ipst->ips_propinfo_tbl;
8879 break;
8880 case MOD_PROTO_RAWIP:
8881 ptbl = stack->netstack_icmp->is_propinfo_tbl;
8882 break;
8883 case MOD_PROTO_TCP:
8884 ptbl = stack->netstack_tcp->tcps_propinfo_tbl;
8885 break;
8886 case MOD_PROTO_UDP:
8887 ptbl = stack->netstack_udp->us_propinfo_tbl;
8888 break;
8889 case MOD_PROTO_SCTP:
8890 ptbl = stack->netstack_sctp->sctps_propinfo_tbl;
8891 break;
8892 default:
8893 miocnak(q, mp, 0, EINVAL);
8894 return;
8895 }
8896
8897 pinfo = mod_prop_lookup(ptbl, pioc->mpr_name, pioc->mpr_proto);
8898 if (pinfo == NULL) {
8899 miocnak(q, mp, 0, ENOENT);
8900 return;
8901 }
8902
8903 set = (iocp->ioc_cmd == SIOCSETPROP) ? B_TRUE : B_FALSE;
8904 if (set && pinfo->mpi_setf != NULL) {
8905 cr = msg_getcred(mp, NULL);
8906 if (cr == NULL)
8907 cr = iocp->ioc_cr;
8908 err = pinfo->mpi_setf(stack, cr, pinfo, pioc->mpr_ifname,
8909 pioc->mpr_val, pioc->mpr_flags);
8910 } else if (!set && pinfo->mpi_getf != NULL) {
8911 err = pinfo->mpi_getf(stack, pinfo, pioc->mpr_ifname,
8912 pioc->mpr_val, pioc->mpr_valsize, pioc->mpr_flags);
8913 } else {
8914 err = EPERM;
8915 }
8916
8917 if (err != 0) {
8918 miocnak(q, mp, 0, err);
8919 } else {
8920 if (set)
8921 miocack(q, mp, 0, 0);
8922 else /* For get, we need to return back the data */
8923 miocack(q, mp, iocp->ioc_count, 0);
8924 }
8925 }
8926
8927 /*
8928 * process the legacy ND_GET, ND_SET ioctl just for {ip|ip6}_forwarding
8929 * as several routing daemons have unfortunately used this 'unpublished'
8930 * but well-known ioctls.
8931 */
8932 /* ARGSUSED */
8933 static void
8934 ip_process_legacy_nddprop(queue_t *q, mblk_t *mp)
8935 {
8936 struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
8937 mblk_t *mp1 = mp->b_cont;
8938 char *pname, *pval, *buf;
8939 uint_t bufsize, proto;
8940 mod_prop_info_t *pinfo = NULL;
8941 ip_stack_t *ipst;
8942 int err = 0;
8943
8944 ASSERT(CONN_Q(q));
8945 ipst = CONNQ_TO_IPST(q);
8946
8947 if (iocp->ioc_count == 0 || mp1 == NULL) {
8948 miocnak(q, mp, 0, EINVAL);
8949 return;
8950 }
8951
8952 mp1->b_datap->db_lim[-1] = '\0'; /* Force null termination */
8953 pval = buf = pname = (char *)mp1->b_rptr;
8954 bufsize = MBLKL(mp1);
8955
8956 if (strcmp(pname, "ip_forwarding") == 0) {
8957 pname = "forwarding";
8958 proto = MOD_PROTO_IPV4;
8959 } else if (strcmp(pname, "ip6_forwarding") == 0) {
8960 pname = "forwarding";
8961 proto = MOD_PROTO_IPV6;
8962 } else {
8963 miocnak(q, mp, 0, EINVAL);
8964 return;
8965 }
8966
8967 pinfo = mod_prop_lookup(ipst->ips_propinfo_tbl, pname, proto);
8968
8969 switch (iocp->ioc_cmd) {
8970 case ND_GET:
8971 if ((err = pinfo->mpi_getf(ipst->ips_netstack, pinfo, NULL, buf,
8972 bufsize, 0)) == 0) {
8973 miocack(q, mp, iocp->ioc_count, 0);
8974 return;
8975 }
8976 break;
8977 case ND_SET:
8978 /*
8979 * buffer will have property name and value in the following
8980 * format,
8981 * <property name>'\0'<property value>'\0', extract them;
8982 */
8983 while (*pval++)
8984 noop;
8985
8986 if (!*pval || pval >= (char *)mp1->b_wptr) {
8987 err = EINVAL;
8988 } else if ((err = pinfo->mpi_setf(ipst->ips_netstack, NULL,
8989 pinfo, NULL, pval, 0)) == 0) {
8990 miocack(q, mp, 0, 0);
8991 return;
8992 }
8993 break;
8994 default:
8995 err = EINVAL;
8996 break;
8997 }
8998 miocnak(q, mp, 0, err);
8999 }
9000
9001 /*
9002 * Wrapper function for resuming deferred ioctl processing
9003 * Used for SIOCGDSTINFO, SIOCGIP6ADDRPOLICY, SIOCGMSFILTER,
9004 * SIOCSMSFILTER, SIOCGIPMSFILTER, and SIOCSIPMSFILTER currently.
9005 */
9006 /* ARGSUSED */
9007 void
9008 ip_sioctl_copyin_resume(ipsq_t *dummy_ipsq, queue_t *q, mblk_t *mp,
9009 void *dummy_arg)
|