]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ipfilter/ip_fil.c
kern: cpuset: allow jails to modify child jails' roots
[FreeBSD/FreeBSD.git] / contrib / ipfilter / ip_fil.c
1 /*      $FreeBSD$       */
2
3 /*
4  * Copyright (C) 2012 by Darren Reed.
5  *
6  * See the IPFILTER.LICENCE file for details on licencing.
7  *
8  * $Id$
9  */
10 #if !defined(lint)
11 static const char sccsid[] = "@(#)ip_fil.c      2.41 6/5/96 (C) 1993-2000 Darren Reed";
12 static const char rcsid[] = "@(#)$Id$";
13 #endif
14
15 #include "ipf.h"
16 #include "md5.h"
17 #include "ipt.h"
18
19 ipf_main_softc_t        ipfmain;
20
21 static  struct  ifnet **ifneta = NULL;
22 static  int     nifs = 0;
23
24 struct  rtentry;
25
26 static  void    ipf_setifpaddr __P((struct ifnet *, char *));
27 void    init_ifp __P((void));
28 static int      no_output __P((struct ifnet *, struct mbuf *,
29                                struct sockaddr *, struct rtentry *));
30 static int      write_output __P((struct ifnet *, struct mbuf *,
31                                   struct sockaddr *, struct rtentry *));
32
33 struct ifaddr {
34         struct sockaddr_storage ifa_addr;
35 };
36
37 int
38 ipfattach(softc)
39         ipf_main_softc_t *softc;
40 {
41         return 0;
42 }
43
44
45 int
46 ipfdetach(softc)
47         ipf_main_softc_t *softc;
48 {
49         return 0;
50 }
51
52
53 /*
54  * Filter ioctl interface.
55  */
56 int
57 ipfioctl(softc, dev, cmd, data, mode)
58         ipf_main_softc_t *softc;
59         int dev;
60         ioctlcmd_t cmd;
61         caddr_t data;
62         int mode;
63 {
64         int error = 0, unit = 0, uid;
65
66         uid = getuid();
67         unit = dev;
68
69         SPL_NET(s);
70
71         error = ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, NULL);
72         if (error != -1) {
73                 SPL_X(s);
74                 return error;
75         }
76         SPL_X(s);
77         return error;
78 }
79
80
81 void
82 ipf_forgetifp(softc, ifp)
83         ipf_main_softc_t *softc;
84         void *ifp;
85 {
86         register frentry_t *f;
87
88         WRITE_ENTER(&softc->ipf_mutex);
89         for (f = softc->ipf_acct[0][softc->ipf_active]; (f != NULL);
90              f = f->fr_next)
91                 if (f->fr_ifa == ifp)
92                         f->fr_ifa = (void *)-1;
93         for (f = softc->ipf_acct[1][softc->ipf_active]; (f != NULL);
94              f = f->fr_next)
95                 if (f->fr_ifa == ifp)
96                         f->fr_ifa = (void *)-1;
97         for (f = softc->ipf_rules[0][softc->ipf_active]; (f != NULL);
98              f = f->fr_next)
99                 if (f->fr_ifa == ifp)
100                         f->fr_ifa = (void *)-1;
101         for (f = softc->ipf_rules[1][softc->ipf_active]; (f != NULL);
102              f = f->fr_next)
103                 if (f->fr_ifa == ifp)
104                         f->fr_ifa = (void *)-1;
105         RWLOCK_EXIT(&softc->ipf_mutex);
106         ipf_nat_sync(softc, ifp);
107         ipf_lookup_sync(softc, ifp);
108 }
109
110
111 static int
112 no_output(ifp, m, s, rt)
113         struct rtentry *rt;
114         struct ifnet *ifp;
115         struct mbuf *m;
116         struct sockaddr *s;
117 {
118         return 0;
119 }
120
121
122 static int
123 write_output(ifp, m, s, rt)
124         struct rtentry *rt;
125         struct ifnet *ifp;
126         struct mbuf *m;
127         struct sockaddr *s;
128 {
129         char fname[32];
130         mb_t *mb;
131         ip_t *ip;
132         int fd;
133
134         mb = (mb_t *)m;
135         ip = MTOD(mb, ip_t *);
136
137 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
138     defined(__FreeBSD__)
139         sprintf(fname, "/tmp/%s", ifp->if_xname);
140 #else
141         sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
142 #endif
143         fd = open(fname, O_WRONLY|O_APPEND);
144         if (fd == -1) {
145                 perror("open");
146                 return -1;
147         }
148         write(fd, (char *)ip, ntohs(ip->ip_len));
149         close(fd);
150         return 0;
151 }
152
153
154 static void
155 ipf_setifpaddr(ifp, addr)
156         struct ifnet *ifp;
157         char *addr;
158 {
159         struct ifaddr *ifa;
160
161 #if defined(__NetBSD__) || defined(__FreeBSD__)
162         if (ifp->if_addrlist.tqh_first != NULL)
163 #else
164         if (ifp->if_addrlist != NULL)
165 #endif
166                 return;
167
168         ifa = (struct ifaddr *)malloc(sizeof(*ifa));
169 #if defined(__NetBSD__) || defined(__FreeBSD__)
170         ifp->if_addrlist.tqh_first = ifa;
171 #else
172         ifp->if_addrlist = ifa;
173 #endif
174
175         if (ifa != NULL) {
176                 struct sockaddr_in *sin;
177
178                 sin = (struct sockaddr_in *)&ifa->ifa_addr;
179 #ifdef USE_INET6
180                 if (index(addr, ':') != NULL) {
181                         struct sockaddr_in6 *sin6;
182
183                         sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
184                         sin6->sin6_family = AF_INET6;
185                         /* Abort if bad address. */
186                         switch (inet_pton(AF_INET6, addr, &sin6->sin6_addr))
187                         {
188                         case 1:
189                                 break;
190                         case -1:
191                                 perror("inet_pton");
192                                 abort();
193                                 break;
194                         default:
195                                 abort();
196                                 break;
197                         }
198                 } else
199 #endif
200                 {
201                         sin->sin_family = AF_INET;
202                         sin->sin_addr.s_addr = inet_addr(addr);
203                         if (sin->sin_addr.s_addr == 0)
204                                 abort();
205                 }
206         }
207 }
208
209 struct ifnet *
210 get_unit(name, family)
211         char *name;
212         int family;
213 {
214         struct ifnet *ifp, **ifpp, **old_ifneta;
215         char *addr;
216 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
217     defined(__FreeBSD__)
218
219         if (!*name)
220                 return NULL;
221
222         if (name == NULL)
223                 name = "anon0";
224
225         addr = strchr(name, '=');
226         if (addr != NULL)
227                 *addr++ = '\0';
228
229         for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
230                 if (!strcmp(name, ifp->if_xname)) {
231                         if (addr != NULL)
232                                 ipf_setifpaddr(ifp, addr);
233                         return ifp;
234                 }
235         }
236 #else
237         char *s, ifname[LIFNAMSIZ+1];
238
239         if (name == NULL)
240                 name = "anon0";
241
242         addr = strchr(name, '=');
243         if (addr != NULL)
244                 *addr++ = '\0';
245
246         for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
247                 COPYIFNAME(family, ifp, ifname);
248                 if (!strcmp(name, ifname)) {
249                         if (addr != NULL)
250                                 ipf_setifpaddr(ifp, addr);
251                         return ifp;
252                 }
253         }
254 #endif
255
256         if (!ifneta) {
257                 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
258                 if (!ifneta)
259                         return NULL;
260                 ifneta[1] = NULL;
261                 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
262                 if (!ifneta[0]) {
263                         free(ifneta);
264                         return NULL;
265                 }
266                 nifs = 1;
267         } else {
268                 old_ifneta = ifneta;
269                 nifs++;
270                 ifneta = (struct ifnet **)reallocarray(ifneta, nifs + 1, 
271                                                   sizeof(ifp));
272                 if (!ifneta) {
273                         free(old_ifneta);
274                         nifs = 0;
275                         return NULL;
276                 }
277                 ifneta[nifs] = NULL;
278                 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
279                 if (!ifneta[nifs - 1]) {
280                         nifs--;
281                         return NULL;
282                 }
283         }
284         ifp = ifneta[nifs - 1];
285
286 #if defined(__NetBSD__) || defined(__FreeBSD__)
287         TAILQ_INIT(&ifp->if_addrlist);
288 #endif
289 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
290     defined(__FreeBSD__)
291         (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
292 #else
293         s = name + strlen(name) - 1;
294         for (; s > name; s--) {
295                 if (!ISDIGIT(*s)) {
296                         s++;
297                         break;
298                 }
299         }
300                 
301         if ((s > name) && (*s != 0) && ISDIGIT(*s)) {
302                 ifp->if_unit = atoi(s);
303                 ifp->if_name = (char *)malloc(s - name + 1);
304                 (void) strncpy(ifp->if_name, name, s - name);
305                 ifp->if_name[s - name] = '\0';
306         } else {
307                 ifp->if_name = strdup(name);
308                 ifp->if_unit = -1;
309         }
310 #endif
311         ifp->if_output = (void *)no_output;
312
313         if (addr != NULL) {
314                 ipf_setifpaddr(ifp, addr);
315         }
316
317         return ifp;
318 }
319
320
321 char *
322 get_ifname(ifp)
323         struct ifnet *ifp;
324 {
325         static char ifname[LIFNAMSIZ];
326
327 #if defined(__NetBSD__) || defined(__FreeBSD__)
328         sprintf(ifname, "%s", ifp->if_xname);
329 #else
330         if (ifp->if_unit != -1)
331                 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
332         else
333                 strcpy(ifname, ifp->if_name);
334 #endif
335         return ifname;
336 }
337
338
339
340 void
341 init_ifp()
342 {
343         struct ifnet *ifp, **ifpp;
344         char fname[32];
345         int fd;
346
347 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
348     defined(__FreeBSD__)
349         for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
350                 ifp->if_output = (void *)write_output;
351                 sprintf(fname, "/tmp/%s", ifp->if_xname);
352                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
353                 if (fd == -1)
354                         perror("open");
355                 else
356                         close(fd);
357         }
358 #else
359
360         for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
361                 ifp->if_output = (void *)write_output;
362                 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
363                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
364                 if (fd == -1)
365                         perror("open");
366                 else
367                         close(fd);
368         }
369 #endif
370 }
371
372
373 int
374 ipf_fastroute(m, mpp, fin, fdp)
375         mb_t *m, **mpp;
376         fr_info_t *fin;
377         frdest_t *fdp;
378 {
379         struct ifnet *ifp;
380         ip_t *ip = fin->fin_ip;
381         frdest_t node;
382         int error = 0;
383         frentry_t *fr;
384         void *sifp;
385         int sout;
386
387         sifp = fin->fin_ifp;
388         sout = fin->fin_out;
389         fr = fin->fin_fr;
390         ip->ip_sum = 0;
391
392         if (!(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) &&
393             (fdp->fd_type == FRD_DSTLIST)) {
394                 bzero(&node, sizeof(node));
395                 ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node);
396                 fdp = &node;
397         }
398         ifp = fdp->fd_ptr;
399
400         if (ifp == NULL)
401                 return 0;       /* no routing table out here */
402
403         if (fin->fin_out == 0) {
404                 fin->fin_ifp = ifp;
405                 fin->fin_out = 1;
406                 (void) ipf_acctpkt(fin, NULL);
407                 fin->fin_fr = NULL;
408                 if (!fr || !(fr->fr_flags & FR_RETMASK)) {
409                         u_32_t pass;
410
411                         (void) ipf_state_check(fin, &pass);
412                 }
413
414                 switch (ipf_nat_checkout(fin, NULL))
415                 {
416                 case 0 :
417                         break;
418                 case 1 :
419                         ip->ip_sum = 0;
420                         break;
421                 case -1 :
422                         error = -1;
423                         goto done;
424                         break;
425                 }
426
427         }
428
429         m->mb_ifp = ifp;
430         printpacket(fin->fin_out, m);
431
432         (*ifp->if_output)(ifp, (void *)m, NULL, 0);
433 done:
434         fin->fin_ifp = sifp;
435         fin->fin_out = sout;
436         return error;
437 }
438
439
440 int
441 ipf_send_reset(fin)
442         fr_info_t *fin;
443 {
444         ipfkverbose("- TCP RST sent\n");
445         return 0;
446 }
447
448
449 int
450 ipf_send_icmp_err(type, fin, dst)
451         int type;
452         fr_info_t *fin;
453         int dst;
454 {
455         ipfkverbose("- ICMP unreachable sent\n");
456         return 0;
457 }
458
459
460 void
461 m_freem(m)
462         mb_t *m;
463 {
464         return;
465 }
466
467
468 void
469 m_copydata(m, off, len, cp)
470         mb_t *m;
471         int off, len;
472         caddr_t cp;
473 {
474         bcopy((char *)m + off, cp, len);
475 }
476
477
478 int
479 ipfuiomove(buf, len, rwflag, uio)
480         caddr_t buf;
481         int len, rwflag;
482         struct uio *uio;
483 {
484         int left, ioc, num, offset;
485         struct iovec *io;
486         char *start;
487
488         if (rwflag == UIO_READ) {
489                 left = len;
490                 ioc = 0;
491
492                 offset = uio->uio_offset;
493
494                 while ((left > 0) && (ioc < uio->uio_iovcnt)) {
495                         io = uio->uio_iov + ioc;
496                         num = io->iov_len;
497                         if (num > left)
498                                 num = left;
499                         start = (char *)io->iov_base + offset;
500                         if (start > (char *)io->iov_base + io->iov_len) {
501                                 offset -= io->iov_len;
502                                 ioc++;
503                                 continue;
504                         }
505                         bcopy(buf, start, num);
506                         uio->uio_resid -= num;
507                         uio->uio_offset += num;
508                         left -= num;
509                         if (left > 0)
510                                 ioc++;
511                 }
512                 if (left > 0)
513                         return EFAULT;
514         }
515         return 0;
516 }
517
518
519 u_32_t
520 ipf_newisn(fin)
521         fr_info_t *fin;
522 {
523         static int iss_seq_off = 0;
524         u_char hash[16];
525         u_32_t newiss;
526         MD5_CTX ctx;
527
528         /*
529          * Compute the base value of the ISS.  It is a hash
530          * of (saddr, sport, daddr, dport, secret).
531          */
532         MD5Init(&ctx);
533
534         MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
535                   sizeof(fin->fin_fi.fi_src));
536         MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
537                   sizeof(fin->fin_fi.fi_dst));
538         MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
539
540         /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
541
542         MD5Final(hash, &ctx);
543
544         memcpy(&newiss, hash, sizeof(newiss));
545
546         /*
547          * Now increment our "timer", and add it in to
548          * the computed value.
549          *
550          * XXX Use `addin'?
551          * XXX TCP_ISSINCR too large to use?
552          */
553         iss_seq_off += 0x00010000;
554         newiss += iss_seq_off;
555         return newiss;
556 }
557
558
559 /* ------------------------------------------------------------------------ */
560 /* Function:    ipf_nextipid                                                */
561 /* Returns:     int - 0 == success, -1 == error (packet should be droppped) */
562 /* Parameters:  fin(I) - pointer to packet information                      */
563 /*                                                                          */
564 /* Returns the next IPv4 ID to use for this packet.                         */
565 /* ------------------------------------------------------------------------ */
566 INLINE u_short
567 ipf_nextipid(fin)
568         fr_info_t *fin;
569 {
570         static u_short ipid = 0;
571         ipf_main_softc_t *softc = fin->fin_main_soft;
572         u_short id;
573
574         MUTEX_ENTER(&softc->ipf_rw);
575         if (fin->fin_pktnum != 0) {
576                 /*
577                  * The -1 is for aligned test results.
578                  */
579                 id = (fin->fin_pktnum - 1) & 0xffff;
580         } else {
581         }
582                 id = ipid++;
583         MUTEX_EXIT(&softc->ipf_rw);
584
585         return id;
586 }
587
588
589 INLINE int
590 ipf_checkv4sum(fin)
591         fr_info_t *fin;
592 {
593
594         if (fin->fin_flx & FI_SHORT)
595                 return 1;
596
597         if (ipf_checkl4sum(fin) == -1) {
598                 fin->fin_flx |= FI_BAD;
599                 return -1;
600         }
601         return 0;
602 }
603
604
605 #ifdef  USE_INET6
606 INLINE int
607 ipf_checkv6sum(fin)
608         fr_info_t *fin;
609 {
610         if (fin->fin_flx & FI_SHORT)
611                 return 1;
612
613         if (ipf_checkl4sum(fin) == -1) {
614                 fin->fin_flx |= FI_BAD;
615                 return -1;
616         }
617         return 0;
618 }
619 #endif
620
621
622 #if 0
623 /*
624  * See above for description, except that all addressing is in user space.
625  */
626 int
627 copyoutptr(softc, src, dst, size)
628         void *src, *dst;
629         size_t size;
630 {
631         caddr_t ca;
632
633         bcopy(dst, (char *)&ca, sizeof(ca));
634         bcopy(src, ca, size);
635         return 0;
636 }
637
638
639 /*
640  * See above for description, except that all addressing is in user space.
641  */
642 int
643 copyinptr(src, dst, size)
644         void *src, *dst;
645         size_t size;
646 {
647         caddr_t ca;
648
649         bcopy(src, (char *)&ca, sizeof(ca));
650         bcopy(ca, dst, size);
651         return 0;
652 }
653 #endif
654
655
656 /*
657  * return the first IP Address associated with an interface
658  */
659 int
660 ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask)
661         ipf_main_softc_t *softc;
662         int v, atype;
663         void *ifptr;
664         i6addr_t *inp, *inpmask;
665 {
666         struct ifnet *ifp = ifptr;
667         struct ifaddr *ifa;
668
669 #if defined(__NetBSD__) || defined(__FreeBSD__)
670         ifa = ifp->if_addrlist.tqh_first;
671 #else
672         ifa = ifp->if_addrlist;
673 #endif
674         if (ifa != NULL) {
675                 if (v == 4) {
676                         struct sockaddr_in *sin, mask;
677
678                         mask.sin_addr.s_addr = 0xffffffff;
679
680                         sin = (struct sockaddr_in *)&ifa->ifa_addr;
681
682                         return ipf_ifpfillv4addr(atype, sin, &mask,
683                                                  &inp->in4, &inpmask->in4);
684                 }
685 #ifdef USE_INET6
686                 if (v == 6) {
687                         struct sockaddr_in6 *sin6, mask;
688
689                         sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
690                         ((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff;
691                         ((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff;
692                         ((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff;
693                         ((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff;
694                         return ipf_ifpfillv6addr(atype, sin6, &mask,
695                                                  inp, inpmask);
696                 }
697 #endif
698         }
699         return 0;
700 }
701
702
703 /*
704  * This function is not meant to be random, rather just produce a
705  * sequence of numbers that isn't linear to show "randomness".
706  */
707 u_32_t
708 ipf_random()
709 {
710         static unsigned int last = 0xa5a5a5a5;
711         static int calls = 0;
712         int number;
713
714         calls++;
715
716         /*
717          * These are deliberately chosen to ensure that there is some
718          * attempt to test whether the output covers the range in test n18.
719          */
720         switch (calls)
721         {
722         case 1 :
723                 number = 0;
724                 break;
725         case 2 :
726                 number = 4;
727                 break;
728         case 3 :
729                 number = 3999;
730                 break;
731         case 4 :
732                 number = 4000;
733                 break;
734         case 5 :
735                 number = 48999;
736                 break;
737         case 6 :
738                 number = 49000;
739                 break;
740         default :
741                 number = last;
742                 last *= calls;
743                 last++;
744                 number ^= last;
745                 break;
746         }
747         return number;
748 }
749
750
751 int
752 ipf_verifysrc(fin)
753         fr_info_t *fin;
754 {
755         return 1;
756 }
757
758
759 int
760 ipf_inject(fin, m)
761         fr_info_t *fin;
762         mb_t *m;
763 {
764         FREE_MB_T(m);
765
766         return 0;
767 }
768
769
770 u_int
771 ipf_pcksum(fin, hlen, sum)
772         fr_info_t *fin;
773         int hlen;
774         u_int sum;
775 {
776         u_short *sp;
777         u_int sum2;
778         int slen;
779
780         slen = fin->fin_plen - hlen;
781         sp = (u_short *)((u_char *)fin->fin_ip + hlen);
782
783         for (; slen > 1; slen -= 2)
784                 sum += *sp++;
785         if (slen)
786                 sum += ntohs(*(u_char *)sp << 8);
787         while (sum > 0xffff)
788                 sum = (sum & 0xffff) + (sum >> 16);
789         sum2 = (u_short)(~sum & 0xffff);
790
791         return sum2;
792 }
793
794
795 void *
796 ipf_pullup(m, fin, plen)
797         mb_t *m;
798         fr_info_t *fin;
799         int plen;
800 {
801         if (M_LEN(m) >= plen)
802                 return fin->fin_ip;
803
804         /*
805          * Fake ipf_pullup failing
806          */
807         fin->fin_reason = FRB_PULLUP;
808         *fin->fin_mp = NULL;
809         fin->fin_m = NULL;
810         fin->fin_ip = NULL;
811         return NULL;
812 }