1 /* 2 * CDDL HEADER START 3 * 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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * DL_IPV4 MAC Type plugin for the Nemo mac module 28 */ 29 30 #include <sys/types.h> 31 #include <sys/modctl.h> 32 #include <sys/dlpi.h> 33 #include <sys/mac.h> 34 #include <sys/mac_ipv4.h> 35 #include <sys/byteorder.h> 36 #include <sys/strsun.h> 37 #include <netinet/in.h> 38 #include <netinet/ip.h> 39 #include <inet/common.h> 40 #include <inet/ip.h> 41 #include <inet/iptun.h> 42 43 static struct modlmisc mac_ipv4_modlmisc = { 44 &mod_miscops, 45 "IPv4 tunneling MAC plugin" 46 }; 47 48 static struct modlinkage mac_ipv4_modlinkage = { 49 MODREV_1, 50 &mac_ipv4_modlmisc, 51 NULL 52 }; 53 54 static mactype_ops_t mac_ipv4_type_ops; 55 56 int 57 _init(void) 58 { 59 mactype_register_t *mtrp; 60 int err; 61 62 if ((mtrp = mactype_alloc(MACTYPE_VERSION)) == NULL) 63 return (ENOTSUP); 64 mtrp->mtr_ident = MAC_PLUGIN_IDENT_IPV4; 65 mtrp->mtr_ops = &mac_ipv4_type_ops; 66 mtrp->mtr_mactype = DL_IPV4; 67 mtrp->mtr_nativetype = DL_IPV4; 68 mtrp->mtr_addrlen = sizeof (ipaddr_t); 69 if ((err = mactype_register(mtrp)) == 0) { 70 if ((err = mod_install(&mac_ipv4_modlinkage)) != 0) 71 (void) mactype_unregister(MAC_PLUGIN_IDENT_IPV4); 72 } 73 mactype_free(mtrp); 74 return (err); 75 } 76 77 int 78 _fini(void) 79 { 80 int err; 81 if ((err = mactype_unregister(MAC_PLUGIN_IDENT_IPV4)) != 0) 82 return (err); 83 return (mod_remove(&mac_ipv4_modlinkage)); 84 } 85 86 int 87 _info(struct modinfo *modinfop) 88 { 89 return (mod_info(&mac_ipv4_modlinkage, modinfop)); 90 } 91 92 /* 93 * MAC Type plugin operations 94 */ 95 96 /* ARGSUSED */ 97 int 98 mac_ipv4_unicst_verify(const void *addr, void *pdata) 99 { 100 const ipaddr_t *ipaddr = addr; 101 return ((CLASSD(*ipaddr) || (*ipaddr == INADDR_BROADCAST)) ? 102 EINVAL : 0); 103 } 104 105 /* ARGSUSED */ 106 int 107 mac_ipv4_multicst_verify(const void *addr, void *pdata) 108 { 109 /* 110 * IPv4 configured tunnels do not have the concept of link-layer 111 * multicast. 112 */ 113 return (ENOTSUP); 114 } 115 116 /* 117 * Check the legality of an IPv4 tunnel SAP value. The only two acceptable 118 * values are IPPROTO_ENCAP (IPv4 in IPv4) and IPPROTO_IPV6 (IPv6 in IPv4). 119 */ 120 /* ARGSUSED */ 121 boolean_t 122 mac_ipv4_sap_verify(uint32_t sap, uint32_t *bind_sap, void *pdata) 123 { 124 if (sap == IPPROTO_ENCAP || sap == IPPROTO_IPV6 || sap == 0) { 125 if (bind_sap != NULL) 126 *bind_sap = sap; 127 return (B_TRUE); 128 } 129 return (B_FALSE); 130 } 131 132 /* 133 * Build an IPv4 link-layer header for tunneling. If provided, the 134 * template header provided by the driver supplies the header length, type 135 * of service, don't fragment flag, ttl, and potential options (depending 136 * on the header length). 137 */ 138 /* ARGSUSED */ 139 mblk_t * 140 mac_ipv4_header(const void *saddr, const void *daddr, uint32_t sap, void *pdata, 141 mblk_t *payload, size_t extra_len) 142 { 143 struct ip *iphp; 144 struct ip *tmpl_iphp = pdata; 145 mblk_t *mp; 146 size_t hdr_len = sizeof (struct ip); 147 148 if (!mac_ipv4_sap_verify(sap, NULL, NULL)) 149 return (NULL); 150 151 if (tmpl_iphp != NULL) 152 hdr_len = tmpl_iphp->ip_hl * sizeof (uint32_t); 153 154 if ((mp = allocb(hdr_len + extra_len, BPRI_HI)) == NULL) 155 return (NULL); 156 157 iphp = (struct ip *)mp->b_rptr; 158 159 bzero(iphp, hdr_len + extra_len); 160 if (tmpl_iphp != NULL) { 161 bcopy(tmpl_iphp, iphp, hdr_len); 162 } else { 163 iphp->ip_hl = IP_SIMPLE_HDR_LENGTH_IN_WORDS; 164 iphp->ip_off = htons(IP_DF); 165 iphp->ip_ttl = IPTUN_DEFAULT_HOPLIMIT; 166 } 167 168 iphp->ip_v = IPVERSION; 169 iphp->ip_len = 0; 170 iphp->ip_p = (uint8_t)sap; 171 bcopy(saddr, &(iphp->ip_src), sizeof (struct in_addr)); 172 bcopy(daddr, &(iphp->ip_dst), sizeof (struct in_addr)); 173 174 mp->b_wptr += hdr_len; 175 return (mp); 176 } 177 178 /* ARGSUSED */ 179 int 180 mac_ipv4_header_info(mblk_t *mp, void *pdata, mac_header_info_t *hdr_info) 181 { 182 struct ip *iphp; 183 184 if (MBLKL(mp) < sizeof (struct ip)) 185 return (EINVAL); 186 187 iphp = (struct ip *)mp->b_rptr; 188 189 /* 190 * IPv4 tunnels don't have a concept of link-layer multicast since 191 * they have fixed unicast endpoints. 192 */ 193 if (mac_ipv4_unicst_verify(&iphp->ip_dst, NULL) != 0) 194 return (EINVAL); 195 196 hdr_info->mhi_hdrsize = iphp->ip_hl * sizeof (uint32_t); 197 hdr_info->mhi_pktsize = 0; 198 hdr_info->mhi_daddr = (const uint8_t *)&(iphp->ip_dst); 199 hdr_info->mhi_saddr = (const uint8_t *)&(iphp->ip_src); 200 hdr_info->mhi_origsap = hdr_info->mhi_bindsap = iphp->ip_p; 201 hdr_info->mhi_dsttype = MAC_ADDRTYPE_UNICAST; 202 return (0); 203 } 204 205 /* 206 * Plugin data is either NULL or a pointer to an IPv4 header. 207 */ 208 boolean_t 209 mac_ipv4_pdata_verify(void *pdata, size_t pdata_size) 210 { 211 const struct ip *iphp = pdata; 212 213 if (pdata == NULL) 214 return (pdata_size == 0); 215 if (pdata_size < sizeof (struct ip)) 216 return (B_FALSE); 217 /* Make sure that the header length field matches pdata_size */ 218 return (pdata_size == iphp->ip_hl * sizeof (uint32_t)); 219 } 220 221 static mactype_ops_t mac_ipv4_type_ops = { 222 MTOPS_PDATA_VERIFY, 223 mac_ipv4_unicst_verify, 224 mac_ipv4_multicst_verify, 225 mac_ipv4_sap_verify, 226 mac_ipv4_header, 227 mac_ipv4_header_info, 228 mac_ipv4_pdata_verify, 229 NULL, 230 NULL, 231 NULL 232 }; 233