]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/natpt_usrreq.c
06e4a3afdd2b823062331712c8844b160dcc8116
[apple/xnu.git] / bsd / netinet6 / natpt_usrreq.c
1 /* $KAME: natpt_usrreq.c,v 1.9 2000/03/25 07:23:57 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/types.h>
33 #include <sys/param.h>
34 #include <sys/malloc.h>
35 #include <sys/mbuf.h>
36 #include <sys/domain.h>
37 /* FreeBSD330 compiler complain that do not #include ioctl.h in the kernel, */
38 /* Include xxxio.h instead */
39 /* #include <sys/ioctl.h> */
40 #include <sys/ioccom.h>
41 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
42 #include <sys/proc.h>
43 #endif
44 #include <sys/protosw.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/syslog.h>
48 #include <sys/systm.h>
49
50 #include <net/if.h>
51 #include <net/raw_cb.h>
52
53 #include <netinet/in.h>
54 #include <netinet/in_systm.h>
55
56 #include <netinet6/natpt_defs.h>
57 #include <netinet6/natpt_log.h>
58 #include <netinet6/natpt_soctl.h>
59 #include <netinet6/natpt_var.h>
60
61
62 /*
63 *
64 */
65
66 #define NATPTSNDQ (8192)
67 #define NATPTRCVQ (8192)
68
69 u_long natpt_sendspace = NATPTSNDQ;
70 u_long natpt_recvspace = NATPTRCVQ;
71
72 #if defined(__bsdi__) || defined(__FreeBSD__) && __FreeBSD__ <= 2
73 static struct rawcb ptrcb;
74 #else
75 LIST_HEAD(, rawcb) ptrcb;
76 #endif
77
78 static struct sockaddr natpt_dst = {2, PF_INET};
79 #ifdef notused
80 static struct sockaddr natpt_src = {2, PF_INET};
81 #endif
82
83 #if 0
84 int natpt_sosetopt __P((struct socket *, int, struct mbuf *));
85 int natpt_sogetopt __P((struct socket *, int, struct mbuf *));
86 #endif
87
88 static int _natptSetIf __P((caddr_t));
89 static int _natptGetIf __P((caddr_t));
90 static int _natptSetValue __P((caddr_t));
91 static int _natptTestLog __P((caddr_t));
92
93 void natpt_init __P((void));
94
95 #ifdef __bsdi__
96 int natpt_usrreq __P((struct socket *, int,
97 struct mbuf *, struct mbuf *, struct mbuf *));
98 #elif defined(__NetBSD__)
99 int natpt_usrreq __P((struct socket *, int,
100 struct mbuf *, struct mbuf *, struct mbuf *, struct proc *));
101 #endif /* defined(__bsdi__) || defined(__NetBSD__) */
102
103
104 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
105 int natpt_uabort __P((struct socket *));
106 int natpt_uattach __P((struct socket *, int, struct proc *));
107 int natpt_ubind __P((struct socket *, struct sockaddr *, struct proc *));
108 int natpt_uconnect __P((struct socket *, struct sockaddr *, struct proc *));
109 int natpt_udetach __P((struct socket *));
110 int natpt_ucontrol __P((struct socket *, u_long, caddr_t, struct ifnet *, struct proc *));
111 #endif /* defined(__FreeBSD__) && __FreeBSD__ >= 3 */
112
113 int natpt_attach __P((struct socket *, int));
114 int natpt_control __P((struct socket *, int, caddr_t, struct ifnet *));
115 int natpt_detach __P((struct socket *));
116 int natpt_disconnect __P((struct socket *));
117
118
119 #ifdef __FreeBSD__
120 #if __FreeBSD__ >= 3
121 struct pr_usrreqs natpt_usrreqs =
122 {
123 natpt_uabort, NULL, natpt_uattach, natpt_ubind,
124 natpt_uconnect, NULL, natpt_ucontrol, natpt_udetach,
125 natpt_disconnect, NULL, NULL, NULL,
126 NULL, NULL, NULL, NULL,
127 NULL, sosend, soreceive, sopoll
128 };
129 #else
130 struct pr_usrreqs natpt_usrreqs =
131 {
132 NULL, NULL, natpt_attach, NULL,
133 NULL, NULL, natpt_control, natpt_detach,
134 natpt_disconnect, NULL, NULL, NULL,
135 NULL, NULL, NULL, NULL,
136 NULL
137 };
138 #endif /* __FreeBSD__ >= 3 */
139 #endif /* __FreeBSD__ */
140
141
142 /*
143 *
144 */
145
146 void
147 natpt_init()
148 {
149 natpt_initialized = 0;
150 ip6_protocol_tr = 0;
151
152 init_tslot();
153
154 #if defined(__bsdi__) || defined(__FreeBSD__) && __FreeBSD__ <= 2
155 ptrcb.rcb_next = ptrcb.rcb_prev = &ptrcb;
156 #else
157 LIST_INIT(&ptrcb);
158 #endif
159
160 printf("NATPT: initialized.\n");
161 }
162
163
164 void
165 natpt_input(struct mbuf *m0, struct sockproto *proto,
166 struct sockaddr *src, struct sockaddr *dst)
167 {
168 struct rawcb *rp;
169 struct mbuf *m = m0;
170 struct socket *last;
171 int sockets;
172
173 last = 0;
174 #if defined(__bsdi__) || defined(__FreeBSD__) && __FreeBSD__ <= 2
175 for (rp = ptrcb.rcb_next; rp != &ptrcb; rp = rp->rcb_next)
176 #else
177 for (rp = ptrcb.lh_first; rp != 0; rp = rp->rcb_list.le_next)
178 #endif
179 {
180 if (rp->rcb_proto.sp_family != proto->sp_family)
181 continue;
182 if (rp->rcb_proto.sp_protocol
183 && (rp->rcb_proto.sp_protocol != proto->sp_protocol))
184 continue;
185
186 #define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
187
188 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
189 continue;
190 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
191 continue;
192
193 if (last)
194 {
195 struct mbuf *n;
196
197 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL)
198 {
199 if (sbappendaddr(&last->so_rcv, src, n, (struct mbuf *)NULL) == 0)
200 m_freem(n); /* should notify about lost packet */
201 else
202 {
203 sorwakeup(last);
204 sockets++;
205 }
206 }
207 }
208 last = rp->rcb_socket;
209 }
210
211 if (last)
212 {
213 if (sbappendaddr(&last->so_rcv, src, m, (struct mbuf *)NULL) == 0)
214 m_freem(m);
215 else
216 {
217 sorwakeup(last);
218 sockets++;
219 }
220 }
221 else
222 m_freem(m);
223 }
224
225
226 #if defined(__bsdi__) || defined(__NetBSD__)
227 int
228 natpt_usrreq(struct socket *so, int req,
229 struct mbuf *m, struct mbuf *nam, struct mbuf *control
230 #ifdef __NetBSD__
231 ,struct proc *p
232 #endif
233 )
234 {
235 struct rawcb *rp = sotorawcb(so);
236 int error = 0;
237
238 if ((rp == NULL) && (req != PRU_ATTACH))
239 {
240 m_freem(m);
241 return (EINVAL);
242 }
243
244 switch (req)
245 {
246 case PRU_ATTACH:
247 error = natpt_attach(so, (int)nam);
248 break;
249
250 case PRU_DETACH:
251 error = natpt_detach(so);
252 break;
253
254 case PRU_DISCONNECT:
255 if (rp->rcb_faddr == NULL)
256 {
257 error = ENOTCONN;
258 break;
259 }
260 rp->rcb_faddr = NULL;
261 raw_disconnect(rp);
262 soisdisconnected(so);
263 break;
264
265 case PRU_SEND:
266 case PRU_BIND:
267 case PRU_LISTEN:
268 case PRU_CONNECT:
269 case PRU_ACCEPT:
270 case PRU_SHUTDOWN:
271 case PRU_RCVD:
272 case PRU_ABORT:
273 error = EOPNOTSUPP;
274 break;
275
276 case PRU_CONTROL:
277 error = natpt_control(so, (int)m, (caddr_t)nam, (struct ifnet *)NULL);
278 return (error);
279 break;
280
281 case PRU_SENSE:
282 case PRU_RCVOOB:
283 case PRU_SENDOOB:
284 case PRU_SOCKADDR:
285 case PRU_PEERADDR:
286 case PRU_CONNECT2:
287 case PRU_FASTTIMO:
288 case PRU_SLOWTIMO:
289 case PRU_PROTORCV:
290 case PRU_PROTOSEND:
291 error = EOPNOTSUPP;
292 break;
293
294 default:
295 panic("raw_usrreq");
296 }
297
298 if (m != NULL)
299 m_freem(m);
300
301 return (error);
302 }
303 #endif /* defined(__bsdi__) || defined(__NetBSD__) */
304
305
306 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
307 int
308 natpt_uabort(struct socket *so)
309 {
310 struct rawcb *rp = sotorawcb(so);
311
312 if (rp == 0)
313 return (EINVAL);
314
315 raw_disconnect(rp);
316 sofree(so);
317 soisdisconnected(so);
318
319 return (0);
320 }
321
322
323 int
324 natpt_uattach(struct socket *so, int proto, struct proc *p)
325 {
326 int error;
327
328 #if ISFB31
329 if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0)
330 return (error);
331 #else
332 if ((so->so_state & SS_PRIV) != 0)
333 return (EPERM);
334 #endif
335
336 return (natpt_attach(so, proto));
337 }
338
339
340 int
341 natpt_ubind(struct socket *so, struct sockaddr *nam, struct proc *p)
342 {
343 return (EINVAL);
344 }
345
346
347 int
348 natpt_uconnect(struct socket *so, struct sockaddr *nam, struct proc *p)
349 {
350 return (EINVAL);
351 }
352
353
354 int
355 natpt_ucontrol(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
356 struct proc *p)
357 {
358 return (natpt_control(so, cmd, data, ifp));
359 }
360
361
362 int
363 natpt_udetach(struct socket *so)
364 {
365 struct rawcb *rp = sotorawcb(so);
366
367 if (rp == 0)
368 return (EINVAL);
369
370 return (natpt_detach(so));
371 }
372
373 #endif /* defined(__FreeBSD__) && __FreeBSD__ >= 3 */
374
375
376 int
377 natpt_attach(struct socket *so, int proto)
378 {
379 struct rawcb *rp;
380 int error;
381
382 if (so->so_pcb == NULL)
383 {
384 MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);
385 so->so_pcb = (caddr_t)rp;
386 bzero(rp, sizeof(*rp));
387 }
388
389 if ((rp = sotorawcb(so)) == NULL)
390 return (ENOBUFS);
391 if ((error = soreserve(so, natpt_sendspace, natpt_recvspace)))
392 return (error);
393
394 rp->rcb_socket = so;
395 rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family;
396 rp->rcb_proto.sp_protocol = proto;
397 #if defined(__bsdi__) || defined(__FreeBSD__) && __FreeBSD__ <= 2
398 insque(rp, &ptrcb);
399 #else
400 LIST_INSERT_HEAD(&ptrcb, rp, rcb_list);
401 #endif
402
403 /* The socket is always "connected" because
404 we always know "where" to send the packet */
405 rp->rcb_faddr = &natpt_dst;
406 soisconnected(so);
407
408 return (0);
409 }
410
411
412 int
413 natpt_detach(struct socket *so)
414 {
415 struct rawcb *rp = sotorawcb(so);
416
417 if (rp == NULL)
418 return (ENOTCONN);
419
420 so->so_pcb = NULL;
421 sofree(so);
422
423 #if defined(__bsdi__) || defined(__FreeBSD__) && __FreeBSD__ <= 2
424 remque(rp);
425 #else
426 LIST_REMOVE(rp, rcb_list);
427 #endif
428 if (rp->rcb_laddr)
429 m_freem(dtom(rp->rcb_laddr));
430 if (rp->rcb_faddr)
431 m_freem(dtom(rp->rcb_faddr));
432 FREE(rp, M_PCB);
433
434 return (0);
435 }
436
437
438 int
439 natpt_disconnect(struct socket *so)
440 {
441 struct rawcb *rp = sotorawcb(so);
442
443 if (rp == NULL)
444 return (EINVAL);
445
446 if (rp->rcb_faddr == NULL)
447 return (ENOTCONN);
448
449 rp->rcb_faddr = NULL;
450 raw_disconnect(rp);
451 soisdisconnected(so);
452
453 return (0);
454 }
455
456
457 int
458 natpt_control(struct socket *so, int cmd, caddr_t data, struct ifnet *ifp)
459 {
460 if (natpt_initialized == 0)
461 natpt_initialize();
462
463 switch (cmd)
464 {
465 case SIOCSETIF: return (_natptSetIf(data));
466 case SIOCGETIF: return (_natptGetIf(data));
467 case SIOCENBTRANS: return (_natptEnableTrans(data));
468 case SIOCDSBTRANS: return (_natptDisableTrans(data));
469 case SIOCSETRULE: return (_natptSetRule(data));
470 case SIOCFLUSHRULE: return (_natptFlushRule(data));
471 case SIOCSETPREFIX: return (_natptSetPrefix(data));
472 case SIOCSETVALUE: return (_natptSetValue(data));
473
474 case SIOCTESTLOG: return (_natptTestLog(data));
475
476 case SIOCBREAK: return (_natptBreak());
477 }
478
479 return (EINVAL);
480 }
481
482
483 /*
484 *
485 */
486
487 static int
488 _natptSetIf(caddr_t addr)
489 {
490 struct natpt_msgBox *mbx = (struct natpt_msgBox *)addr;
491 struct ifBox *ifb;
492
493 if (((ifb = natpt_asIfBox(mbx->m_ifName)) == NULL)
494 && ((ifb = natpt_setIfBox(mbx->m_ifName)) == NULL))
495 return (ENXIO);
496
497 if (ifb->side != noSide)
498 {
499 char WoW[LBFSZ];
500
501 sprintf(WoW, "[natpt]: interface `%s\' already configured.", mbx->m_ifName);
502 natpt_logMsg(LOG_WARNING, WoW, strlen(WoW));
503 return (EALREADY);
504 }
505
506 {
507 char WoW[LBFSZ];
508 char *s;
509
510 natpt_ip6src = ifb->ifnet;
511 if (mbx->flags == IF_EXTERNAL)
512 ifb->side = outSide, s = "outside";
513 else
514 ifb->side = inSide, s = "inside";
515
516 sprintf(WoW, "[natpt]: interface `%s\' set as %s.", mbx->m_ifName, s);
517 natpt_logMsg(LOG_INFO, WoW, strlen(WoW));
518 }
519
520 return (0);
521 }
522
523
524 static int
525 _natptGetIf(caddr_t addr)
526 {
527 struct natpt_msgBox *mbx = (struct natpt_msgBox *)addr;
528 struct ifBox *ifb;
529
530 if (((ifb = natpt_asIfBox(mbx->m_ifName)) == NULL)
531 && ((ifb = natpt_setIfBox(mbx->m_ifName)) == NULL))
532 return (ENXIO);
533
534 {
535 switch (ifb->side)
536 {
537 case outSide: mbx->flags |= IF_EXTERNAL; break;
538 case inSide: mbx->flags |= IF_INTERNAL; break;
539 default: mbx->flags = -1; break;
540 }
541 }
542
543 return (0);
544 }
545
546
547 static int
548 _natptSetValue(caddr_t addr)
549 {
550 struct natpt_msgBox *mbx = (struct natpt_msgBox *)addr;
551
552 switch (mbx->flags)
553 {
554 case NATPT_DEBUG:
555 natpt_debug = *((u_int *)mbx->m_aux);
556 break;
557
558 case NATPT_DUMP:
559 natpt_dump = *((u_int *)mbx->m_aux);
560 break;
561 }
562
563 return (0);
564 }
565
566
567 static int
568 _natptTestLog(caddr_t addr)
569 {
570 char *fragile;
571 struct natpt_msgBox *mbox = (struct natpt_msgBox *)addr;
572
573 MALLOC(fragile, char *, mbox->size, M_TEMP, M_WAITOK);
574 copyin(mbox->freight, fragile, mbox->size);
575
576 natpt_logMsg(LOG_DEBUG, fragile, mbox->size);
577
578 FREE(fragile, M_TEMP);
579 return (0);
580 }
581