]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/natpt_rule.c
xnu-201.5.tar.gz
[apple/xnu.git] / bsd / netinet6 / natpt_rule.c
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
63 Cell *natptStatic; /* list of struct _cSlot */
64 Cell *natptDynamic; /* list of struct _cSlot */
65 Cell *natptFaith; /* list of struct _cSlot */
66
67 int matchIn4addr __P((struct _cv *, struct pAddr *));
68 int matchIn6addr __P((struct _cv *, struct pAddr *));
69 static void _flushPtrRules __P((struct _cell **));
70
71
72 extern struct in6_addr faith_prefix;
73 extern struct in6_addr faith_prefixmask;
74 extern struct in6_addr natpt_prefix;
75 extern struct in6_addr natpt_prefixmask;
76
77 extern void in4_len2mask __P((struct in_addr *, int));
78 extern void in6_len2mask __P((struct in6_addr *, int));
79
80
81 /*
82 *
83 */
84
85 struct _cSlot *
86 lookingForIncomingV4Rule(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
115 struct _cSlot *
116 lookingForOutgoingV4Rule(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
142 struct _cSlot *
143 lookingForIncomingV6Rule(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
168 struct _cSlot *
169 lookingForOutgoingV6Rule(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
208 int
209 matchIn4addr(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
239 port:;
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
263 int
264 matchIn6addr(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
293 port:;
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
322 int
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
335 int
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
348 int
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
405 int
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
420 int
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
435 int
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
466 int
467 _natptBreak()
468 {
469 printf("break");
470
471 return (0);
472 }
473
474
475 /*
476 *
477 */
478
479 static 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 }