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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * DL_IPV4 MAC Type plugin for the Nemo mac module
30 #include <sys/types.h>
31 #include <sys/modctl.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>
41 #include <inet/iptun.h>
43 static struct modlmisc mac_ipv4_modlmisc
= {
45 "IPv4 tunneling MAC plugin"
48 static struct modlinkage mac_ipv4_modlinkage
= {
54 static mactype_ops_t mac_ipv4_type_ops
;
59 mactype_register_t
*mtrp
;
62 if ((mtrp
= mactype_alloc(MACTYPE_VERSION
)) == NULL
)
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
);
81 if ((err
= mactype_unregister(MAC_PLUGIN_IDENT_IPV4
)) != 0)
83 return (mod_remove(&mac_ipv4_modlinkage
));
87 _info(struct modinfo
*modinfop
)
89 return (mod_info(&mac_ipv4_modlinkage
, modinfop
));
93 * MAC Type plugin operations
98 mac_ipv4_unicst_verify(const void *addr
, void *pdata
)
100 const ipaddr_t
*ipaddr
= addr
;
101 return ((CLASSD(*ipaddr
) || (*ipaddr
== INADDR_BROADCAST
)) ?
107 mac_ipv4_multicst_verify(const void *addr
, void *pdata
)
110 * IPv4 configured tunnels do not have the concept of link-layer
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).
122 mac_ipv4_sap_verify(uint32_t sap
, uint32_t *bind_sap
, void *pdata
)
124 if (sap
== IPPROTO_ENCAP
|| sap
== IPPROTO_IPV6
|| sap
== 0) {
125 if (bind_sap
!= NULL
)
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).
140 mac_ipv4_header(const void *saddr
, const void *daddr
, uint32_t sap
, void *pdata
,
141 mblk_t
*payload
, size_t extra_len
)
144 struct ip
*tmpl_iphp
= pdata
;
146 size_t hdr_len
= sizeof (struct ip
);
148 if (!mac_ipv4_sap_verify(sap
, NULL
, NULL
))
151 if (tmpl_iphp
!= NULL
)
152 hdr_len
= tmpl_iphp
->ip_hl
* sizeof (uint32_t);
154 if ((mp
= allocb(hdr_len
+ extra_len
, BPRI_HI
)) == NULL
)
157 iphp
= (struct ip
*)mp
->b_rptr
;
159 bzero(iphp
, hdr_len
+ extra_len
);
160 if (tmpl_iphp
!= NULL
) {
161 bcopy(tmpl_iphp
, iphp
, hdr_len
);
163 iphp
->ip_hl
= IP_SIMPLE_HDR_LENGTH_IN_WORDS
;
164 iphp
->ip_off
= htons(IP_DF
);
165 iphp
->ip_ttl
= IPTUN_DEFAULT_HOPLIMIT
;
168 iphp
->ip_v
= IPVERSION
;
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
));
174 mp
->b_wptr
+= hdr_len
;
180 mac_ipv4_header_info(mblk_t
*mp
, void *pdata
, mac_header_info_t
*hdr_info
)
184 if (MBLKL(mp
) < sizeof (struct ip
))
187 iphp
= (struct ip
*)mp
->b_rptr
;
190 * IPv4 tunnels don't have a concept of link-layer multicast since
191 * they have fixed unicast endpoints.
193 if (mac_ipv4_unicst_verify(&iphp
->ip_dst
, NULL
) != 0)
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
;
206 * Plugin data is either NULL or a pointer to an IPv4 header.
209 mac_ipv4_pdata_verify(void *pdata
, size_t pdata_size
)
211 const struct ip
*iphp
= pdata
;
214 return (pdata_size
== 0);
215 if (pdata_size
< sizeof (struct ip
))
217 /* Make sure that the header length field matches pdata_size */
218 return (pdata_size
== iphp
->ip_hl
* sizeof (uint32_t));
221 static mactype_ops_t mac_ipv4_type_ops
= {
223 mac_ipv4_unicst_verify
,
224 mac_ipv4_multicst_verify
,
227 mac_ipv4_header_info
,
228 mac_ipv4_pdata_verify
,