]> git.saurik.com Git - apple/network_cmds.git/blame - racoon.tproj/isakmp_natd.c
network_cmds-176.2.1.tar.gz
[apple/network_cmds.git] / racoon.tproj / isakmp_natd.c
CommitLineData
ac2f15b3
A
1
2#include <sys/types.h>
3#include <sys/queue.h>
4#include <sys/socket.h>
5#include <netinet/in.h>
6#include <arpa/inet.h>
7
8#include <string.h>
9
10#include "vmbuf.h"
11#include "plog.h"
12#include "misc.h"
13#include "isakmp_var.h"
14#include "oakley.h"
15#include "isakmp.h"
16
17#include "handler.h"
18#include "isakmp_natd.h"
19
20natd_match_t
21natd_matches(
22 struct ph1handle* iph1,
23 struct isakmp_gen *natd_record)
24{
25 natd_match_t matches = 0;
26#ifdef IKE_NAT_T
27 int dataLen = ntohs(natd_record->len) - sizeof(*natd_record);
28 char* dataPtr = ((char*)natd_record) + sizeof(*natd_record);
29
30 /* Always recreate the natd records in case the ports change */
31 natd_create(iph1);
32
33 if (iph1->local_natd != NULL && dataLen == iph1->local_natd->l &&
34 memcmp(dataPtr, iph1->local_natd->v, dataLen) == 0)
35 {
36 plog(LLV_DEBUG, LOCATION, iph1->remote,
37 "natd payload matches local address\n");
38 matches |= natd_match_local;
39 }
40
41 if (iph1->remote_natd != NULL && dataLen == iph1->remote_natd->l &&
42 memcmp(dataPtr, iph1->remote_natd->v, dataLen) == 0)
43 {
44 plog(LLV_DEBUG, LOCATION, iph1->remote,
45 "natd payload matches remote address\n");
46 matches |= natd_match_remote;
47 }
48#else
49 matches = natd_match_local | natd_match_remote;
50#endif
51
52 if (matches == 0)
53 {
54 plog(LLV_DEBUG, LOCATION, iph1->remote,
55 "natd payload matches no address\n");
56 }
57
58 return matches;
59}
60
61/*
62 * NAT detection record contains a hash of the initiator cookie,
63 * responder cookie, address, and port.
64 */
65typedef struct {
66 cookie_t initiator_cookie;
67 cookie_t responder_cookie;
68 struct in_addr address;
69 u_short port;
70} __attribute__((__packed__)) natd_hash_contents;
71
72int
73natd_create(
74 struct ph1handle* iph1)
75{
76#ifdef IKE_NAT_T
77 natd_hash_contents hash_this;
78 vchar_t data_to_hash;
79
80 if (iph1->remote->sa_family != AF_INET ||
81 iph1->local->sa_family != AF_INET)
82 {
83 /*
84 * NAT traversal is intentionally unsupported on IPv6.
85 *
86 * The only reason for using NAT is a lack of addresses.
87 * IPv6 does not suffer from a lack of addresses. If I
88 * find that anyone is using NAT with IPv6, I would break
89 * their kneecaps and poke their eyes out with sharp
90 * sticks. I don't really want to go to jail though, so
91 * instead, I'll spare myself the effort of support nat
92 * traversal magic when IPv6 is involved in hopes this will
93 * cause boneheads who would try to use IPv6 NAT to give up
94 * since so many things will stop working. I'm sick of
95 * working around all of the problems that NATs introduce.
96 *
97 * IPv6 is our opportunity to move to a NAT free world.
98 */
99 return -1;
100 }
101
102 data_to_hash.l = sizeof(hash_this);
103 data_to_hash.v = (char*)&hash_this;
104
105 memcpy(hash_this.initiator_cookie, iph1->index.i_ck,
106 sizeof(hash_this.initiator_cookie));
107 memcpy(hash_this.responder_cookie, iph1->index.r_ck,
108 sizeof(hash_this.responder_cookie));
109
110 /* Local address */
111 if (iph1->local_natd != NULL)
112 vfree(iph1->local_natd);
113 iph1->local_natd = NULL;
114 hash_this.address = ((struct sockaddr_in*)(iph1->local))->sin_addr;
115 hash_this.port = ((struct sockaddr_in*)(iph1->local))->sin_port;
116 plog(LLV_DEBUG, LOCATION, iph1->remote,
117 "creating local %.8X%.8X:%.8X%.8X %s:%d\n",
118 *(u_long*)&hash_this.initiator_cookie[0],
119 *(u_long*)&hash_this.initiator_cookie[4],
120 *(u_long*)&hash_this.responder_cookie[0],
121 *(u_long*)&hash_this.responder_cookie[4],
122 inet_ntoa(hash_this.address), hash_this.port);
123 iph1->local_natd = oakley_hash(&data_to_hash, iph1);
124 plogdump(LLV_DEBUG, iph1->local_natd->v, iph1->local_natd->l);
125
126 /* Remote address */
127 if (iph1->remote_natd != NULL)
128 vfree(iph1->remote_natd);
129 iph1->remote_natd = NULL;
130 hash_this.address = ((struct sockaddr_in*)(iph1->remote))->sin_addr;
131 hash_this.port = ((struct sockaddr_in*)(iph1->remote))->sin_port;
132 plog(LLV_DEBUG, LOCATION, iph1->remote,
133 "creating remote %.8X%.8X:%.8X%.8X %s:%d\n",
134 *(u_long*)&hash_this.initiator_cookie[0],
135 *(u_long*)&hash_this.initiator_cookie[4],
136 *(u_long*)&hash_this.responder_cookie[0],
137 *(u_long*)&hash_this.responder_cookie[4],
138 inet_ntoa(hash_this.address), hash_this.port);
139 iph1->remote_natd = oakley_hash(&data_to_hash, iph1);
140 plogdump(LLV_DEBUG, iph1->remote_natd->v, iph1->remote_natd->l);
141
142 return (iph1->local_natd != NULL) && (iph1->remote_natd != NULL);
143#else
144 return 0;
145#endif
146}
147
148int
149natd_hasnat(
150 const struct ph1handle* iph1)
151{
152#if IKE_NAT_T
153 return (iph1->natt_flags & natt_natd_received) &&
154 (iph1->natt_flags & (natt_no_remote_nat | natt_no_local_nat)) !=
155 (natt_no_remote_nat | natt_no_local_nat);
156#else
157 return 0;
158#endif
159}