2 * TAP-Win32 -- A kernel driver to provide virtual tap device functionality
3 * on Windows. Originally derived from the CIPE-Win32
4 * project by Damion K. Wilson, with extensive modifications by
7 * All source code which derives from the CIPE-Win32 project is
8 * Copyright (C) Damion K. Wilson, 2003, and is released under the
9 * GPL version 2 (see below).
11 * All other source code is Copyright (C) 2002-2005 OpenVPN Solutions LLC,
12 * and is released under the GPL version 2 (see below).
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2
16 * as published by the Free Software Foundation.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program (see the file COPYING included with this
25 * distribution); if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 //=========================
30 // Code to set DHCP options
31 //=========================
34 SetDHCPOpt (DHCPMsg
*m
, void *data
, unsigned int len
)
38 if (m
->optlen
+ len
<= DHCP_OPTIONS_BUFFER_SIZE
)
42 NdisMoveMemory (m
->msg
.options
+ m
->optlen
, data
, len
);
54 SetDHCPOpt0 (DHCPMsg
*msg
, int type
)
57 opt
.type
= (UCHAR
) type
;
58 SetDHCPOpt (msg
, &opt
, sizeof (opt
));
62 SetDHCPOpt8 (DHCPMsg
*msg
, int type
, ULONG data
)
65 opt
.type
= (UCHAR
) type
;
66 opt
.len
= sizeof (opt
.data
);
67 opt
.data
= (UCHAR
) data
;
68 SetDHCPOpt (msg
, &opt
, sizeof (opt
));
72 SetDHCPOpt32 (DHCPMsg
*msg
, int type
, ULONG data
)
75 opt
.type
= (UCHAR
) type
;
76 opt
.len
= sizeof (opt
.data
);
78 SetDHCPOpt (msg
, &opt
, sizeof (opt
));
86 ip_checksum (const UCHAR
*buf
, const int len_ip_header
)
92 // make 16 bit words out of every two adjacent 8 bit words in the packet
94 for (i
= 0; i
< len_ip_header
- 1; i
+= 2) {
95 word16
= ((buf
[i
] << 8) & 0xFF00) + (buf
[i
+1] & 0xFF);
96 sum
+= (ULONG
) word16
;
99 // take only 16 bits out of the 32 bit sum and add up the carries
101 sum
= (sum
& 0xFFFF) + (sum
>> 16);
103 // one's complement the result
104 return ((USHORT
) ~sum
);
108 udp_checksum (const UCHAR
*buf
,
110 const UCHAR
*src_addr
,
111 const UCHAR
*dest_addr
)
117 // make 16 bit words out of every two adjacent 8 bit words and
118 // calculate the sum of all 16 bit words
119 for (i
= 0; i
< len_udp
; i
+= 2){
120 word16
= ((buf
[i
] << 8) & 0xFF00) + ((i
+ 1 < len_udp
) ? (buf
[i
+1] & 0xFF) : 0);
124 // add the UDP pseudo header which contains the IP source and destination addresses
125 for (i
= 0; i
< 4; i
+= 2){
126 word16
=((src_addr
[i
] << 8) & 0xFF00) + (src_addr
[i
+1] & 0xFF);
129 for (i
= 0; i
< 4; i
+= 2){
130 word16
=((dest_addr
[i
] << 8) & 0xFF00) + (dest_addr
[i
+1] & 0xFF);
134 // the protocol number and the length of the UDP packet
135 sum
+= (USHORT
) IPPROTO_UDP
+ (USHORT
) len_udp
;
137 // keep only the last 16 bits of the 32 bit calculated sum and add the carries
139 sum
= (sum
& 0xFFFF) + (sum
>> 16);
141 // Take the one's complement of sum
142 return ((USHORT
) ~sum
);
145 //================================
146 // Set IP and UDP packet checksums
147 //================================
150 SetChecksumDHCPMsg (DHCPMsg
*m
)
153 m
->msg
.pre
.ip
.check
= htons (ip_checksum ((UCHAR
*) &m
->msg
.pre
.ip
, sizeof (IPHDR
)));
156 m
->msg
.pre
.udp
.check
= htons (udp_checksum ((UCHAR
*) &m
->msg
.pre
.udp
,
157 sizeof (UDPHDR
) + sizeof (DHCP
) + m
->optlen
,
158 (UCHAR
*)&m
->msg
.pre
.ip
.saddr
,
159 (UCHAR
*)&m
->msg
.pre
.ip
.daddr
));
162 //===================
163 // DHCP message tests
164 //===================
167 GetDHCPMessageType (const DHCP
*dhcp
, const int optlen
)
169 const UCHAR
*p
= (UCHAR
*) (dhcp
+ 1);
172 for (i
= 0; i
< optlen
; ++i
)
174 const UCHAR type
= p
[i
];
175 const int room
= optlen
- i
- 1;
176 if (type
== DHCP_END
) // didn't find what we were looking for
178 else if (type
== DHCP_PAD
) // no-operation
180 else if (type
== DHCP_MSG_TYPE
) // what we are looking for
184 if (p
[i
+1] == 1) // message length should be 1
185 return p
[i
+2]; // return message type
189 else // some other message
193 const int len
= p
[i
+1]; // get message length
194 i
+= (len
+ 1); // advance to next message
202 DHCPMessageOurs (const TapAdapterPointer p_Adapter
,
203 const ETH_HEADER
*eth
,
208 // Must be UDPv4 protocol
209 if (!(eth
->proto
== htons (ETH_P_IP
) && ip
->protocol
== IPPROTO_UDP
))
212 // Source MAC must be our adapter
213 if (!MAC_EQUAL (eth
->src
, p_Adapter
->m_MAC
))
216 // Dest MAC must be either broadcast or our virtual DHCP server
217 if (!(MAC_EQUAL (eth
->dest
, p_Adapter
->m_MAC_Broadcast
)
218 || MAC_EQUAL (eth
->dest
, p_Adapter
->m_dhcp_server_mac
)))
221 // Port numbers must be correct
222 if (!(udp
->dest
== htons (BOOTPS_PORT
)
223 && udp
->source
== htons (BOOTPC_PORT
)))
226 // Hardware address must be MAC addr sized
227 if (!(dhcp
->hlen
== sizeof (MACADDR
)))
230 // Hardware address must match our adapter
231 if (!MAC_EQUAL (eth
->src
, dhcp
->chaddr
))
238 //=====================================================
239 // Build all of DHCP packet except for DHCP options.
240 // Assume that *p has been zeroed before we are called.
241 //=====================================================
244 BuildDHCPPre (const TapAdapterPointer a
,
246 const ETH_HEADER
*eth
,
253 // Should we broadcast or direct to a specific MAC / IP address?
254 const BOOLEAN broadcast
= (type
== DHCPNAK
255 || MAC_EQUAL (eth
->dest
, a
->m_MAC_Broadcast
));
256 // Build ethernet header
258 COPY_MAC (p
->eth
.src
, a
->m_dhcp_server_mac
);
261 COPY_MAC (p
->eth
.dest
, a
->m_MAC_Broadcast
);
263 COPY_MAC (p
->eth
.dest
, eth
->src
);
265 p
->eth
.proto
= htons (ETH_P_IP
);
269 p
->ip
.version_len
= (4 << 4) | (sizeof (IPHDR
) >> 2);
271 p
->ip
.tot_len
= htons (sizeof (IPHDR
) + sizeof (UDPHDR
) + sizeof (DHCP
) + optlen
);
275 p
->ip
.protocol
= IPPROTO_UDP
;
277 p
->ip
.saddr
= a
->m_dhcp_server_ip
;
282 p
->ip
.daddr
= a
->m_dhcp_addr
;
286 p
->udp
.source
= htons (BOOTPS_PORT
);
287 p
->udp
.dest
= htons (BOOTPC_PORT
);
288 p
->udp
.len
= htons (sizeof (UDPHDR
) + sizeof (DHCP
) + optlen
);
291 // Build DHCP response
293 p
->dhcp
.op
= BOOTREPLY
;
295 p
->dhcp
.hlen
= sizeof (MACADDR
);
297 p
->dhcp
.xid
= dhcp
->xid
;
305 p
->dhcp
.yiaddr
= a
->m_dhcp_addr
;
307 p
->dhcp
.siaddr
= a
->m_dhcp_server_ip
;
309 COPY_MAC (p
->dhcp
.chaddr
, eth
->src
);
310 p
->dhcp
.magic
= htonl (0x63825363);
312 //=============================
313 // Build specific DHCP messages
314 //=============================
317 SendDHCPMsg (const TapAdapterPointer a
,
319 const ETH_HEADER
*eth
,
326 if (!(type
== DHCPOFFER
|| type
== DHCPACK
|| type
== DHCPNAK
))
328 DEBUGP (("[TAP] SendDHCPMsg: Bad DHCP type: %d\n", type
));
332 pkt
= (DHCPMsg
*) MemAlloc (sizeof (DHCPMsg
), TRUE
);
336 //-----------------------
337 // Build DHCP options
338 //-----------------------
341 SetDHCPOpt8 (pkt
, DHCP_MSG_TYPE
, type
);
344 SetDHCPOpt32 (pkt
, DHCP_SERVER_ID
, a
->m_dhcp_server_ip
);
346 if (type
== DHCPOFFER
|| type
== DHCPACK
)
349 SetDHCPOpt32 (pkt
, DHCP_LEASE_TIME
, htonl (a
->m_dhcp_lease_time
));
352 SetDHCPOpt32 (pkt
, DHCP_NETMASK
, a
->m_dhcp_netmask
);
354 // Other user-defined options
356 a
->m_dhcp_user_supplied_options_buffer
,
357 a
->m_dhcp_user_supplied_options_buffer_len
);
361 SetDHCPOpt0 (pkt
, DHCP_END
);
363 if (!DHCPMSG_OVERFLOW (pkt
))
365 // The initial part of the DHCP message (not including options) gets built here
372 DHCPMSG_LEN_OPT (pkt
),
375 SetChecksumDHCPMsg (pkt
);
377 DUMP_PACKET ("DHCPMsg",
379 DHCPMSG_LEN_FULL (pkt
));
381 // Return DHCP response to kernel
384 DHCPMSG_LEN_FULL (pkt
));
388 DEBUGP (("[TAP] SendDHCPMsg: DHCP buffer overflow\n"));
391 MemFree (pkt
, sizeof (DHCPMsg
));
395 //===================================================================
396 // Handle a BOOTPS packet produced by the local system to
397 // resolve the address/netmask of this adapter.
398 // If we are in TAP_IOCTL_CONFIG_DHCP_MASQ mode, reply
399 // to the message. Return TRUE if we processed the passed
400 // message, so that downstream stages can ignore it.
401 //===================================================================
404 ProcessDHCP (TapAdapterPointer p_Adapter
,
405 const ETH_HEADER
*eth
,
413 // Sanity check IP header
414 if (!(ntohs (ip
->tot_len
) == sizeof (IPHDR
) + sizeof (UDPHDR
) + sizeof (DHCP
) + optlen
415 && (ntohs (ip
->frag_off
) & IP_OFFMASK
) == 0))
418 // Does this message belong to us?
419 if (!DHCPMessageOurs (p_Adapter
, eth
, ip
, udp
, dhcp
))
422 msg_type
= GetDHCPMessageType (dhcp
, optlen
);
424 // Drop non-BOOTREQUEST messages
425 if (dhcp
->op
!= BOOTREQUEST
)
428 // Drop any messages except DHCPDISCOVER or DHCPREQUEST
429 if (!(msg_type
== DHCPDISCOVER
|| msg_type
== DHCPREQUEST
))
432 // Should we reply with DHCPOFFER, DHCPACK, or DHCPNAK?
433 if (msg_type
== DHCPREQUEST
434 && ((dhcp
->ciaddr
&& dhcp
->ciaddr
!= p_Adapter
->m_dhcp_addr
)
435 || !p_Adapter
->m_dhcp_received_discover
436 || p_Adapter
->m_dhcp_bad_requests
>= BAD_DHCPREQUEST_NAK_THRESHOLD
))
437 SendDHCPMsg (p_Adapter
,
441 SendDHCPMsg (p_Adapter
,
442 (msg_type
== DHCPDISCOVER
? DHCPOFFER
: DHCPACK
),
445 // Remember if we received a DHCPDISCOVER
446 if (msg_type
== DHCPDISCOVER
)
447 p_Adapter
->m_dhcp_received_discover
= TRUE
;
449 // Is this a bad DHCPREQUEST?
450 if (msg_type
== DHCPREQUEST
&& dhcp
->ciaddr
!= p_Adapter
->m_dhcp_addr
)
451 ++p_Adapter
->m_dhcp_bad_requests
;
459 message_op_text (int op
)
464 return "BOOTREQUEST";
473 message_type_text (int type
)
478 return "DHCPDISCOVER";
482 return "DHCPREQUEST";
484 return "DHCPDECLINE";
490 return "DHCPRELEASE";
513 DumpDHCP (const ETH_HEADER
*eth
,
519 DEBUGP ((" %s", message_op_text (dhcp
->op
)));
520 DEBUGP ((" %s ", message_type_text (GetDHCPMessageType (dhcp
, optlen
))));
522 DEBUGP ((":%s[", port_name (ntohs (udp
->source
))));
526 DEBUGP ((":%s[", port_name (ntohs (udp
->dest
))));
544 if (dhcp
->hlen
== sizeof (MACADDR
))
547 PrMac (dhcp
->chaddr
);
550 DEBUGP ((" xid=0x%08x", ntohl (dhcp
->xid
)));
552 if (ntohl (dhcp
->magic
) != 0x63825363)
553 DEBUGP ((" ma=0x%08x", ntohl (dhcp
->magic
)));
554 if (dhcp
->htype
!= 1)
555 DEBUGP ((" htype=%d", dhcp
->htype
));
557 DEBUGP ((" hops=%d", dhcp
->hops
));
558 if (ntohs (dhcp
->secs
))
559 DEBUGP ((" secs=%d", ntohs (dhcp
->secs
)));
560 if (ntohs (dhcp
->flags
))
561 DEBUGP ((" flags=0x%04x", ntohs (dhcp
->flags
)));
565 if (ip
->version_len
!= 0x45)
566 DEBUGP ((" vl=0x%02x", ip
->version_len
));
567 if (ntohs (ip
->tot_len
) != sizeof (IPHDR
) + sizeof (UDPHDR
) + sizeof (DHCP
) + optlen
)
568 DEBUGP ((" tl=%d", ntohs (ip
->tot_len
)));
569 if (ntohs (udp
->len
) != sizeof (UDPHDR
) + sizeof (DHCP
) + optlen
)
570 DEBUGP ((" ul=%d", ntohs (udp
->len
)));
573 DEBUGP ((" tos=0x%02x", ip
->tos
));
575 DEBUGP ((" id=0x%04x", ntohs (ip
->id
)));
576 if (ntohs (ip
->frag_off
))
577 DEBUGP ((" frag_off=0x%04x", ntohs (ip
->frag_off
)));
579 DEBUGP ((" ttl=%d", ip
->ttl
));
580 DEBUGP ((" ic=0x%04x [0x%04x]", ntohs (ip
->check
),
581 ip_checksum ((UCHAR
*)ip
, sizeof (IPHDR
))));
582 DEBUGP ((" uc=0x%04x [0x%04x/%d]", ntohs (udp
->check
),
583 udp_checksum ((UCHAR
*) udp
,
584 sizeof (UDPHDR
) + sizeof (DHCP
) + optlen
,
585 (UCHAR
*) &ip
->saddr
,
586 (UCHAR
*) &ip
->daddr
),
591 const UCHAR
*opt
= (UCHAR
*) (dhcp
+ 1);
595 for (i
= 0; i
< optlen
; ++i
)
597 const UCHAR data
= opt
[i
];
598 DEBUGP ((".%d", data
));