win-pvdrivers

view xennet/xennet_common.c @ 649:cbd4e4ae9527

Fix missing reg delete in uninstaller
author James Harper <james.harper@bendigoit.com.au>
date Mon Sep 07 13:26:25 2009 +1000 (2009-09-07)
parents 0436238bcda5
children 31c56358c9fc
line source
1 /*
2 PV Net Driver for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
4 Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
21 #include "xennet.h"
23 /*
24 Increase the header to a certain size
25 */
27 BOOLEAN
28 XenNet_BuildHeader(packet_info_t *pi, ULONG new_header_size)
29 {
30 ULONG bytes_remaining;
32 //FUNCTION_ENTER();
34 if (new_header_size <= pi->header_length)
35 {
36 return TRUE; /* header is already at least the required size */
37 }
39 if (pi->header == pi->first_buffer_virtual)
40 {
41 /* still working in the first buffer */
42 if (new_header_size <= pi->first_buffer_length)
43 {
44 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " new_header_size <= pi->first_buffer_length\n"));
45 pi->header_length = new_header_size;
46 if (pi->header_length == pi->first_buffer_length)
47 {
48 NdisGetNextBuffer(pi->curr_buffer, &pi->curr_buffer);
49 pi->curr_mdl_offset = 0;
50 }
51 else
52 {
53 pi->curr_mdl_offset = (USHORT)new_header_size;
54 if (pi->curr_pb)
55 pi->curr_pb = pi->curr_pb->next;
56 }
57 return TRUE;
58 }
59 else
60 {
61 //KdPrint((__DRIVER_NAME " Switching to header_data\n"));
62 memcpy(pi->header_data, pi->header, pi->header_length);
63 pi->header = pi->header_data;
64 }
65 }
67 bytes_remaining = new_header_size - pi->header_length;
69 //KdPrint((__DRIVER_NAME " A bytes_remaining = %d, pi->curr_buffer = %p, pi->mdl_count = %d\n", bytes_remaining, pi->curr_buffer, pi->mdl_count));
70 while (bytes_remaining && pi->curr_buffer)
71 {
72 ULONG copy_size;
74 ASSERT(pi->curr_buffer);
75 //KdPrint((__DRIVER_NAME " B bytes_remaining = %d, pi->curr_buffer = %p, pi->mdl_count = %d\n", bytes_remaining, pi->curr_buffer, pi->mdl_count));
76 if (MmGetMdlByteCount(pi->curr_buffer))
77 {
78 PUCHAR src_addr;
79 src_addr = MmGetSystemAddressForMdlSafe(pi->curr_buffer, NormalPagePriority);
80 if (!src_addr)
81 return FALSE;
82 copy_size = min(bytes_remaining, MmGetMdlByteCount(pi->curr_buffer) - pi->curr_mdl_offset);
83 //KdPrint((__DRIVER_NAME " B copy_size = %d\n", copy_size));
84 memcpy(pi->header + pi->header_length,
85 src_addr + pi->curr_mdl_offset, copy_size);
86 pi->curr_mdl_offset = (USHORT)(pi->curr_mdl_offset + copy_size);
87 pi->header_length += copy_size;
88 bytes_remaining -= copy_size;
89 }
90 if (pi->curr_mdl_offset == MmGetMdlByteCount(pi->curr_buffer))
91 {
92 NdisGetNextBuffer(pi->curr_buffer, &pi->curr_buffer);
93 if (pi->curr_pb)
94 pi->curr_pb = pi->curr_pb->next;
95 pi->curr_mdl_offset = 0;
96 }
97 }
98 //KdPrint((__DRIVER_NAME " C bytes_remaining = %d, pi->curr_buffer = %p, pi->mdl_count = %d\n", bytes_remaining, pi->curr_buffer, pi->mdl_count));
99 if (bytes_remaining)
100 {
101 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " bytes_remaining\n"));
102 return FALSE;
103 }
104 //FUNCTION_EXIT();
105 return TRUE;
106 }
108 ULONG
109 XenNet_ParsePacketHeader(packet_info_t *pi, PUCHAR alt_buffer, ULONG min_header_size)
110 {
111 //FUNCTION_ENTER();
113 ASSERT(pi->first_buffer);
115 NdisQueryBufferSafe(pi->first_buffer, (PVOID)&pi->first_buffer_virtual, &pi->first_buffer_length, NormalPagePriority);
116 pi->curr_buffer = pi->first_buffer;
117 if (alt_buffer)
118 pi->header = alt_buffer;
119 else
120 pi->header = pi->first_buffer_virtual;
122 pi->header_length = 0;
123 pi->curr_mdl_offset = 0;
125 if (!XenNet_BuildHeader(pi, max((ULONG)XN_HDR_SIZE, min_header_size)))
126 {
127 KdPrint((__DRIVER_NAME " packet too small (Ethernet Header)\n"));
128 return PARSE_TOO_SMALL;
129 }
131 switch (GET_NET_PUSHORT(&pi->header[12])) // L2 protocol field
132 {
133 case 0x0800:
134 //KdPrint((__DRIVER_NAME " IP\n"));
135 if (pi->header_length < (ULONG)(XN_HDR_SIZE + 20))
136 {
137 if (!XenNet_BuildHeader(pi, (ULONG)(XN_HDR_SIZE + 20)))
138 {
139 KdPrint((__DRIVER_NAME " packet too small (IP Header)\n"));
140 return PARSE_TOO_SMALL;
141 }
142 }
143 pi->ip_version = (pi->header[XN_HDR_SIZE + 0] & 0xF0) >> 4;
144 if (pi->ip_version != 4)
145 {
146 KdPrint((__DRIVER_NAME " ip_version = %d\n", pi->ip_version));
147 return PARSE_UNKNOWN_TYPE;
148 }
149 pi->ip4_header_length = (pi->header[XN_HDR_SIZE + 0] & 0x0F) << 2;
150 if (pi->header_length < (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + 20))
151 {
152 if (!XenNet_BuildHeader(pi, (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + 20)))
153 {
154 //KdPrint((__DRIVER_NAME " packet too small (IP Header + IP Options + TCP Header)\n"));
155 return PARSE_TOO_SMALL;
156 }
157 }
158 break;
159 default:
160 //KdPrint((__DRIVER_NAME " Not IP (%d)\n", GET_NET_PUSHORT(&pi->header[12])));
161 return PARSE_UNKNOWN_TYPE;
162 }
163 pi->ip_proto = pi->header[XN_HDR_SIZE + 9];
164 switch (pi->ip_proto)
165 {
166 case 6: // TCP
167 case 17: // UDP
168 break;
169 default:
170 //KdPrint((__DRIVER_NAME " Not TCP/UDP (%d)\n", pi->ip_proto));
171 return PARSE_UNKNOWN_TYPE;
172 }
173 pi->ip4_length = GET_NET_PUSHORT(&pi->header[XN_HDR_SIZE + 2]);
174 pi->tcp_header_length = (pi->header[XN_HDR_SIZE + pi->ip4_header_length + 12] & 0xf0) >> 2;
176 if (pi->header_length < (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + pi->tcp_header_length))
177 {
178 if (!XenNet_BuildHeader(pi, (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + pi->tcp_header_length)))
179 {
180 //KdPrint((__DRIVER_NAME " packet too small (IP Header + IP Options + TCP Header + TCP Options)\n"));
181 return PARSE_TOO_SMALL;
182 }
183 }
185 if ((ULONG)XN_HDR_SIZE + pi->ip4_length > pi->total_length)
186 {
187 KdPrint((__DRIVER_NAME " XN_HDR_SIZE + ip4_length (%d) > total_length (%d)\n", XN_HDR_SIZE + pi->ip4_length, pi->total_length));
188 return PARSE_UNKNOWN_TYPE;
189 }
191 pi->tcp_length = pi->ip4_length - pi->ip4_header_length - pi->tcp_header_length;
192 pi->tcp_remaining = pi->tcp_length;
193 pi->tcp_seq = GET_NET_PULONG(&pi->header[XN_HDR_SIZE + pi->ip4_header_length + 4]);
194 pi->tcp_has_options = (BOOLEAN)(pi->tcp_header_length > 20);
195 if (pi->mss > 0 && pi->tcp_length > pi->mss)
196 pi->split_required = TRUE;
198 //KdPrint((__DRIVER_NAME " ip4_length = %d\n", pi->ip4_length));
199 //KdPrint((__DRIVER_NAME " tcp_length = %d\n", pi->tcp_length));
200 //FUNCTION_EXIT();
202 return PARSE_OK;
203 }
205 VOID
206 XenNet_SumIpHeader(
207 PUCHAR header,
208 USHORT ip4_header_length
209 )
210 {
211 ULONG csum = 0;
212 USHORT i;
214 ASSERT(ip4_header_length > 12);
215 ASSERT(!(ip4_header_length & 1));
217 header[XN_HDR_SIZE + 10] = 0;
218 header[XN_HDR_SIZE + 11] = 0;
219 for (i = 0; i < ip4_header_length; i += 2)
220 {
221 csum += GET_NET_PUSHORT(&header[XN_HDR_SIZE + i]);
222 }
223 while (csum & 0xFFFF0000)
224 csum = (csum & 0xFFFF) + (csum >> 16);
225 csum = ~csum;
226 SET_NET_USHORT(&header[XN_HDR_SIZE + 10], (USHORT)csum);
227 }