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 /* 23 * Copyright 2008-2013 Solarflare Communications Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/sysmacros.h> 29 #include <sys/ddi.h> 30 #include <sys/sunddi.h> 31 #include <sys/stream.h> 32 #include <sys/strsun.h> 33 #include <sys/strsubr.h> 34 #include <sys/pattr.h> 35 36 #include <sys/ethernet.h> 37 #include <inet/ip.h> 38 39 #include <netinet/in.h> 40 #include <netinet/ip.h> 41 #include <netinet/tcp.h> 42 43 #include "sfxge.h" 44 45 #include "efx.h" 46 47 void 48 sfxge_tcp_parse(mblk_t *mp, struct ether_header **etherhpp, struct ip **iphpp, 49 struct tcphdr **thpp, size_t *offp, size_t *sizep) 50 { 51 struct ether_header *etherhp; 52 uint16_t ether_type; 53 size_t etherhs; 54 struct ip *iphp; 55 size_t iphs; 56 struct tcphdr *thp; 57 size_t ths; 58 size_t off; 59 size_t size; 60 61 etherhp = NULL; 62 iphp = NULL; 63 thp = NULL; 64 off = 0; 65 size = 0; 66 67 /* Grab the MAC header */ 68 if (MBLKL(mp) < sizeof (struct ether_header)) 69 if (!pullupmsg(mp, sizeof (struct ether_header))) 70 goto done; 71 72 /*LINTED*/ 73 etherhp = (struct ether_header *)(mp->b_rptr); 74 ether_type = etherhp->ether_type; 75 etherhs = sizeof (struct ether_header); 76 77 if (ether_type == htons(ETHERTYPE_VLAN)) { 78 struct ether_vlan_header *ethervhp; 79 80 if (MBLKL(mp) < sizeof (struct ether_vlan_header)) 81 if (!pullupmsg(mp, sizeof (struct ether_vlan_header))) 82 goto done; 83 84 /*LINTED*/ 85 ethervhp = (struct ether_vlan_header *)(mp->b_rptr); 86 ether_type = ethervhp->ether_type; 87 etherhs = sizeof (struct ether_vlan_header); 88 } 89 90 if (ether_type != htons(ETHERTYPE_IP)) 91 goto done; 92 93 /* Skip over the MAC header */ 94 off += etherhs; 95 96 /* Grab the IP header */ 97 if (MBLKL(mp) < off + sizeof (struct ip)) 98 if (!pullupmsg(mp, off + sizeof (struct ip))) 99 goto done; 100 101 /*LINTED*/ 102 iphp = (struct ip *)(mp->b_rptr + off); 103 iphs = iphp->ip_hl * 4; 104 105 if (iphp->ip_v != IPV4_VERSION) 106 goto done; 107 108 /* Get the size of the packet */ 109 size = ntohs(iphp->ip_len); 110 111 ASSERT3U(etherhs + size, <=, msgdsize(mp)); 112 113 if (iphp->ip_p != IPPROTO_TCP) 114 goto done; 115 116 /* Skip over the IP header */ 117 off += iphs; 118 size -= iphs; 119 120 /* Grab the TCP header */ 121 if (MBLKL(mp) < off + sizeof (struct tcphdr)) 122 if (!pullupmsg(mp, off + sizeof (struct tcphdr))) 123 goto done; 124 125 /*LINTED*/ 126 thp = (struct tcphdr *)(mp->b_rptr + off); 127 ths = thp->th_off * 4; 128 129 /* Skip over the TCP header */ 130 off += ths; 131 size -= ths; 132 133 if (MBLKL(mp) < off) 134 (void) pullupmsg(mp, off); 135 136 done: 137 *etherhpp = etherhp; 138 *iphpp = iphp; 139 *thpp = thp; 140 *offp = off; 141 *sizep = size; 142 }