]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/natpt_rule.c
xnu-201.19.3.tar.gz
[apple/xnu.git] / bsd / netinet6 / natpt_rule.c
CommitLineData
1c79356b
A
1/* $KAME: natpt_rule.c,v 1.9 2000/03/25 07:23:56 sumikawa Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/errno.h>
33#include <sys/param.h>
34#include <sys/malloc.h>
35#include <sys/mbuf.h>
36#include <sys/socket.h>
37#include <sys/syslog.h>
38#include <sys/systm.h>
39
40#include <net/if.h>
41
42#include <netinet/in.h>
43#include <netinet/in_systm.h>
44#include <netinet/ip.h>
45#include <netinet/tcp.h>
46
47#include <netinet/ip6.h>
48#if (defined(__FreeBSD__) && __FreeBSD__ < 3) || defined(__bsdi__)
49#include <netinet6/tcp6.h>
50#endif
51
52#include <netinet6/natpt_defs.h>
53#include <netinet6/natpt_list.h>
54#include <netinet6/natpt_log.h>
55#include <netinet6/natpt_soctl.h>
56#include <netinet6/natpt_var.h>
57
58
59/*
60 *
61 */
62
63Cell *natptStatic; /* list of struct _cSlot */
64Cell *natptDynamic; /* list of struct _cSlot */
65Cell *natptFaith; /* list of struct _cSlot */
66
67int matchIn4addr __P((struct _cv *, struct pAddr *));
68int matchIn6addr __P((struct _cv *, struct pAddr *));
69static void _flushPtrRules __P((struct _cell **));
70
71
72extern struct in6_addr faith_prefix;
73extern struct in6_addr faith_prefixmask;
74extern struct in6_addr natpt_prefix;
75extern struct in6_addr natpt_prefixmask;
76
77extern void in4_len2mask __P((struct in_addr *, int));
78extern void in6_len2mask __P((struct in6_addr *, int));
79
80
81/*
82 *
83 */
84
85struct _cSlot *
86lookingForIncomingV4Rule(struct _cv *cv)
87{
88 Cell *p;
89 struct _cSlot *acs;
90
91 for (p = natptStatic; p; p = CDR(p))
92 {
93 acs = (struct _cSlot *)CAR(p);
94 if ((acs->dir == NATPT_INBOUND)
95 && ((acs->proto == 0)
96 || (acs->proto == cv->ip_payload))
97 && (matchIn4addr(cv, &acs->remote) != 0))
98 return (acs);
99 }
100
101 for (p = natptDynamic; p; p = CDR(p))
102 {
103 acs = (struct _cSlot *)CAR(p);
104 if ((acs->dir == NATPT_INBOUND)
105 && ((acs->proto == 0)
106 || (acs->proto == cv->ip_payload))
107 && (matchIn4addr(cv, &acs->remote) != 0))
108 return (acs);
109 }
110
111 return (NULL);
112}
113
114
115struct _cSlot *
116lookingForOutgoingV4Rule(struct _cv *cv)
117{
118 Cell *p;
119 struct _cSlot *acs;
120
121 for (p = natptStatic; p; p = CDR(p))
122 {
123 acs = (struct _cSlot *)CAR(p);
124
125 if ((acs->dir == NATPT_OUTBOUND)
126 && (matchIn4addr(cv, &acs->local) != 0))
127 return (acs);
128 }
129
130 for (p = natptDynamic; p; p = CDR(p))
131 {
132 acs = (struct _cSlot *)CAR(p);
133 if ((acs->dir == NATPT_OUTBOUND)
134 && (matchIn4addr(cv, &acs->local) != 0))
135 return (acs);
136 }
137
138 return (NULL);
139}
140
141
142struct _cSlot *
143lookingForIncomingV6Rule(struct _cv *cv)
144{
145 Cell *p;
146 struct _cSlot *acs;
147
148 for (p = natptStatic; p; p = CDR(p))
149 {
150 acs = (struct _cSlot *)CAR(p);
151 if ((acs->dir == NATPT_INBOUND)
152 && (matchIn6addr(cv, &acs->remote)) != 0)
153 return (acs);
154 }
155
156 for (p = natptDynamic; p; p = CDR(p))
157 {
158 acs = (struct _cSlot *)CAR(p);
159 if ((acs->dir == NATPT_INBOUND)
160 && (matchIn6addr(cv, &acs->remote)) != 0)
161 return (acs);
162 }
163
164 return (NULL);
165}
166
167
168struct _cSlot *
169lookingForOutgoingV6Rule(struct _cv *cv)
170{
171 Cell *p;
172 struct _cSlot *acs;
173
174 for (p = natptStatic; p; p = CDR(p))
175 {
176 acs = (struct _cSlot *)CAR(p);
177 if ((acs->dir == NATPT_OUTBOUND)
178 && ((acs->proto == 0)
179 || (acs->proto == cv->ip_payload))
180 && (matchIn6addr(cv, &acs->local)) != 0)
181 return (acs);
182 }
183
184 for (p = natptDynamic; p; p = CDR(p))
185 {
186 acs = (struct _cSlot *)CAR(p);
187 if ((acs->dir == NATPT_OUTBOUND)
188 && ((acs->proto == 0)
189 || (acs->proto == cv->ip_payload))
190 && (matchIn6addr(cv, &acs->local)) != 0)
191 return (acs);
192 }
193
194 for (p = natptFaith; p; p = CDR(p))
195 {
196 acs = (struct _cSlot *)CAR(p);
197 if ((acs->dir == NATPT_OUTBOUND)
198 && ((acs->proto == 0)
199 || (acs->proto == cv->ip_payload))
200 && (matchIn6addr(cv, &acs->local)) != 0)
201 return (acs);
202 }
203
204 return (NULL);
205}
206
207
208int
209matchIn4addr(struct _cv *cv4, struct pAddr *from)
210{
211 struct in_addr in4from = cv4->_ip._ip4->ip_src;
212 struct in_addr in4masked;
213
214 if (from->sa_family != AF_INET)
215 return (0);
216
217 switch (from->ad.type)
218 {
219 case ADDR_ANY: goto port;
220
221 case ADDR_SINGLE:
222 if (in4from.s_addr == from->in4Addr.s_addr) goto port;
223 return (0);
224
225 case ADDR_MASK:
226 in4masked.s_addr = in4from.s_addr & from->in4Mask.s_addr;
227 if (in4masked.s_addr == from->in4Addr.s_addr) goto port;
228 return (0);
229
230 case ADDR_RANGE:
231 if ((in4from.s_addr >= from->in4RangeStart.s_addr)
232 && (in4from.s_addr <= from->in4RangeEnd.s_addr)) goto port;
233 return (0);
234
235 default:
236 return (0);
237 }
238
239port:;
240 if ((cv4->ip_payload != IPPROTO_UDP)
241 && (cv4->ip_payload != IPPROTO_TCP)) return (1);
242
243 if (from->_port0 == 0) return (1);
244
245 if (from->_port1 == 0)
246 {
247 if ((cv4->_payload._tcp4->th_dport == from->_port0)) return (1);
248 }
249 else
250 {
251 u_short dport = ntohs(cv4->_payload._tcp4->th_dport);
252 u_short port0 = ntohs(from->_port0);
253 u_short port1 = ntohs(from->_port1);
254
255 if ((dport >= port0)
256 && (dport <= port1)) return (1);
257 }
258
259 return (0);
260}
261
262
263int
264matchIn6addr(struct _cv *cv6, struct pAddr *from)
265{
266 struct in6_addr *in6from = &cv6->_ip._ip6->ip6_src;
267 struct in6_addr in6masked;
268
269 if (from->sa_family != AF_INET6)
270 return (0);
271
272 switch (from->ad.type)
273 {
274 case ADDR_ANY: goto port;
275
276 case ADDR_SINGLE:
277 if (IN6_ARE_ADDR_EQUAL(in6from, &from->in6Addr)) goto port;
278 return (0);
279
280 case ADDR_MASK:
281 in6masked.s6_addr32[0] = in6from->s6_addr32[0] & from->in6Mask.s6_addr32[0];
282 in6masked.s6_addr32[1] = in6from->s6_addr32[1] & from->in6Mask.s6_addr32[1];
283 in6masked.s6_addr32[2] = in6from->s6_addr32[2] & from->in6Mask.s6_addr32[2];
284 in6masked.s6_addr32[3] = in6from->s6_addr32[3] & from->in6Mask.s6_addr32[3];
285
286 if (IN6_ARE_ADDR_EQUAL(&in6masked, &from->in6Addr)) goto port;
287 return (0);
288
289 default:
290 return (0);
291 }
292
293port:;
294 if ((cv6->ip_payload != IPPROTO_UDP)
295 && (cv6->ip_payload != IPPROTO_TCP)) return (1);
296
297 if (from->_port0 == 0) return (1);
298
299 if (from->_port1 == 0)
300 {
301 if (cv6->_payload._tcp6->th_dport == from->_port0) return (1);
302 }
303 else
304 {
305 u_short dport = ntohs(cv6->_payload._tcp6->th_dport);
306#ifdef UnusedVariable
307 u_short port0 = ntohs(from->_port0);
308 u_short port1 = ntohs(from->_port1);
309#endif
310
311 if ((dport >= from->_port0)
312 && (dport <= from->_port1)) return (1);
313 }
314
315
316 return (0);
317}
318/*
319 *
320 */
321
322int
323_natptEnableTrans(caddr_t addr)
324{
325 char Wow[64];
326
327 sprintf(Wow, "map enable");
328 natpt_logMsg(LOG_INFO, Wow, strlen(Wow));
329
330 ip6_protocol_tr = 1;
331 return (0);
332}
333
334
335int
336_natptDisableTrans(caddr_t addr)
337{
338 char Wow[64];
339
340 sprintf(Wow, "map disable");
341 natpt_logMsg(LOG_INFO, Wow, strlen(Wow));
342
343 ip6_protocol_tr = 0;
344 return (0);
345}
346
347
348int
349_natptSetRule(caddr_t addr)
350{
351 struct natpt_msgBox *mbx = (struct natpt_msgBox *)addr;
352 struct _cSlot *cst;
353 Cell **anchor;
354
355#if 0
356 if (((ifb = natpt_asIfBox(mbx->m_ifName)) == NULL)
357 && ((ifb = natpt_setIfBox(mbx->m_ifName)) == NULL))
358 return (ENXIO);
359#endif
360
361 if (mbx->flags == NATPT_FAITH)
362 return (_natptSetFaithRule(addr));
363
364 MALLOC(cst, struct _cSlot *, sizeof(struct _cSlot), M_TEMP, M_WAITOK);
365 copyin(mbx->freight, cst, sizeof(struct _cSlot));
366
367 {
368 struct pAddr *from;
369
370 from = &cst->local;
371 if (cst->dir == NATPT_INBOUND)
372 from = &cst->remote;
373
374 if (from->sa_family == AF_INET)
375 {
376 in4_len2mask(&from->in4Mask, cst->prefix);
377 from->in4Addr.s_addr &= from->in4Mask.s_addr;
378 }
379 else
380 {
381 in6_len2mask(&from->in6Mask, cst->prefix);
382 from->in6Addr.s6_addr32[0]
383 = from->in6Addr.s6_addr32[0] & from->in6Mask.s6_addr32[0];
384 from->in6Addr.s6_addr32[1]
385 = from->in6Addr.s6_addr32[1] & from->in6Mask.s6_addr32[1];
386 from->in6Addr.s6_addr32[2]
387 = from->in6Addr.s6_addr32[2] & from->in6Mask.s6_addr32[2];
388 from->in6Addr.s6_addr32[3]
389 = from->in6Addr.s6_addr32[3] & from->in6Mask.s6_addr32[3];
390 }
391 }
392
393 natpt_log(LOG_CSLOT, LOG_DEBUG, (void *)cst, sizeof(struct _cSlot));
394
395 anchor = &natptStatic;
396 if (cst->flags == NATPT_DYNAMIC)
397 anchor = &natptDynamic;
398
399 LST_hookup_list(anchor, cst);
400
401 return (0);
402}
403
404
405int
406_natptSetFaithRule(caddr_t addr)
407{
408 struct natpt_msgBox *mbx = (struct natpt_msgBox *)addr;
409 struct _cSlot *cst;
410
411 MALLOC(cst, struct _cSlot *, sizeof(struct _cSlot), M_TEMP, M_WAITOK);
412 copyin(mbx->freight, cst, sizeof(struct _cSlot));
413
414 LST_hookup_list(&natptFaith, cst);
415
416 return (0);
417}
418
419
420int
421_natptFlushRule(caddr_t addr)
422{
423 struct natpt_msgBox *mbx = (struct natpt_msgBox *)addr;
424
425 if (mbx->flags & FLUSH_STATIC)
426 _flushPtrRules(&natptStatic);
427
428 if (mbx->flags & FLUSH_DYNAMIC)
429 _flushPtrRules(&natptDynamic);
430
431 return (0);
432}
433
434
435int
436_natptSetPrefix(caddr_t addr)
437{
438 struct natpt_msgBox *mbx = (struct natpt_msgBox *)addr;
439 struct pAddr *load;
440
441 MALLOC(load, struct pAddr *, sizeof(struct pAddr), M_TEMP, M_WAITOK);
442 copyin(mbx->freight, load, SZSIN6 * 2);
443
444 if (mbx->flags & PREFIX_FAITH)
445 {
446 faith_prefix = load->addr[0].in6;
447 faith_prefixmask = load->addr[1].in6;
448
449 natpt_logIN6addr(LOG_INFO, "FAITH prefix: ", &faith_prefix);
450 natpt_logIN6addr(LOG_INFO, "FAITH prefixmask: ", &faith_prefixmask);
451 }
452 else if (mbx->flags & PREFIX_NATPT)
453 {
454 natpt_prefix = load->addr[0].in6;
455 natpt_prefixmask = load->addr[1].in6;
456
457 natpt_logIN6addr(LOG_INFO, "NATPT prefix: ", &natpt_prefix);
458 natpt_logIN6addr(LOG_INFO, "NATPT prefixmask: ", &natpt_prefixmask);
459 }
460
461 FREE(load, M_TEMP);
462 return (0);
463}
464
465
466int
467_natptBreak()
468{
469 printf("break");
470
471 return (0);
472}
473
474
475/*
476 *
477 */
478
479static void
480_flushPtrRules(struct _cell **anchor)
481{
482 struct _cell *p0, *p1;
483 struct _cSlot *cslt;
484
485 p0 = *anchor;
486 while (p0)
487 {
488 p1 = p0;
489 p0 = CDR(p0);
490
491 cslt = (struct _cSlot *)CAR(p1);
492 FREE(cslt, M_TEMP);
493 LST_free(p1);
494 }
495
496 *anchor = NULL;
497}