1 1.39 mrg /* $NetBSD: ip_fil_netbsd.c,v 1.39 2024/06/09 20:30:36 mrg Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (C) 2012 by Darren Reed. 5 1.1 christos * 6 1.1 christos * See the IPFILTER.LICENCE file for details on licencing. 7 1.1 christos */ 8 1.1 christos #if !defined(lint) 9 1.2 christos #if defined(__NetBSD__) 10 1.2 christos #include <sys/cdefs.h> 11 1.39 mrg __KERNEL_RCSID(0, "$NetBSD: ip_fil_netbsd.c,v 1.39 2024/06/09 20:30:36 mrg Exp $"); 12 1.2 christos #else 13 1.1 christos static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 14 1.3 darrenr static const char rcsid[] = "@(#)Id: ip_fil_netbsd.c,v 1.1.1.2 2012/07/22 13:45:17 darrenr Exp"; 15 1.2 christos #endif 16 1.1 christos #endif 17 1.1 christos 18 1.1 christos #if defined(KERNEL) || defined(_KERNEL) 19 1.1 christos # undef KERNEL 20 1.1 christos # undef _KERNEL 21 1.1 christos # define KERNEL 1 22 1.1 christos # define _KERNEL 1 23 1.1 christos #endif 24 1.1 christos #include <sys/param.h> 25 1.1 christos #if (NetBSD >= 199905) && !defined(IPFILTER_LKM) 26 1.13 pgoyette # if (__NetBSD_Version__ >= 799003000) 27 1.13 pgoyette # ifdef _KERNEL_OPT 28 1.13 pgoyette # include "opt_ipsec.h" 29 1.13 pgoyette # endif 30 1.13 pgoyette # else 31 1.13 pgoyette # include "opt_ipsec.h" 32 1.13 pgoyette # endif 33 1.1 christos #endif 34 1.1 christos #include <sys/errno.h> 35 1.1 christos #include <sys/types.h> 36 1.1 christos #include <sys/file.h> 37 1.1 christos #include <sys/ioctl.h> 38 1.1 christos #include <sys/time.h> 39 1.1 christos #include <sys/systm.h> 40 1.1 christos #include <sys/select.h> 41 1.1 christos #if (NetBSD > 199609) 42 1.1 christos # include <sys/dirent.h> 43 1.1 christos #else 44 1.1 christos # include <sys/dir.h> 45 1.1 christos #endif 46 1.1 christos #if (__NetBSD_Version__ >= 599005900) 47 1.1 christos # include <sys/cprng.h> 48 1.1 christos #endif 49 1.1 christos #include <sys/mbuf.h> 50 1.1 christos #include <sys/protosw.h> 51 1.1 christos #include <sys/socket.h> 52 1.1 christos #include <sys/poll.h> 53 1.1 christos #if (__NetBSD_Version__ >= 399002000) 54 1.1 christos # include <sys/kauth.h> 55 1.1 christos #endif 56 1.13 pgoyette #if (__NetBSD_Version__ >= 799003000) 57 1.13 pgoyette #include <sys/module.h> 58 1.13 pgoyette #include <sys/mutex.h> 59 1.13 pgoyette #endif 60 1.29 maxv #if defined(__NetBSD__) 61 1.29 maxv #include <netinet/in_offload.h> 62 1.29 maxv #endif 63 1.1 christos 64 1.1 christos #include <net/if.h> 65 1.1 christos #include <net/route.h> 66 1.1 christos #include <netinet/in.h> 67 1.1 christos #include <netinet/in_var.h> 68 1.1 christos #include <netinet/in_systm.h> 69 1.1 christos #include <netinet/ip.h> 70 1.1 christos #include <netinet/ip_var.h> 71 1.1 christos #include <netinet/tcp.h> 72 1.1 christos #if __NetBSD_Version__ >= 105190000 /* 1.5T */ 73 1.1 christos # include <netinet/tcp_timer.h> 74 1.1 christos # include <netinet/tcp_var.h> 75 1.1 christos #endif 76 1.1 christos #include <netinet/udp.h> 77 1.1 christos #include <netinet/ip_icmp.h> 78 1.1 christos #include "netinet/ip_compat.h" 79 1.1 christos #ifdef USE_INET6 80 1.1 christos # include <netinet/icmp6.h> 81 1.1 christos # if (__NetBSD_Version__ >= 106000000) 82 1.1 christos # include <netinet6/nd6.h> 83 1.1 christos # endif 84 1.26 christos # if __NetBSD_Version__ >= 499001100 85 1.26 christos # include <netinet6/scope6_var.h> 86 1.31 maxv # include <netinet6/in6_offload.h> 87 1.26 christos # endif 88 1.1 christos #endif 89 1.1 christos #include "netinet/ip_fil.h" 90 1.1 christos #include "netinet/ip_nat.h" 91 1.1 christos #include "netinet/ip_frag.h" 92 1.1 christos #include "netinet/ip_state.h" 93 1.1 christos #include "netinet/ip_proxy.h" 94 1.1 christos #include "netinet/ip_auth.h" 95 1.1 christos #include "netinet/ip_sync.h" 96 1.1 christos #include "netinet/ip_lookup.h" 97 1.1 christos #include "netinet/ip_dstlist.h" 98 1.1 christos #ifdef IPFILTER_SCAN 99 1.1 christos #include "netinet/ip_scan.h" 100 1.1 christos #endif 101 1.1 christos #include <sys/md5.h> 102 1.1 christos #include <sys/kernel.h> 103 1.1 christos #include <sys/conf.h> 104 1.1 christos #ifdef INET 105 1.2 christos extern int ip_optcopy (struct ip *, struct ip *); 106 1.1 christos #endif 107 1.1 christos 108 1.1 christos #ifdef IPFILTER_M_IPFILTER 109 1.1 christos MALLOC_DEFINE(M_IPFILTER, "IP Filter", "IP Filter packet filter data structures"); 110 1.1 christos #endif 111 1.1 christos 112 1.1 christos #if __NetBSD_Version__ >= 105009999 113 1.1 christos # define csuminfo csum_flags 114 1.1 christos #endif 115 1.1 christos 116 1.1 christos #if __NetBSD_Version__ < 200000000 117 1.1 christos extern struct protosw inetsw[]; 118 1.1 christos #endif 119 1.2 christos 120 1.2 christos #if (__NetBSD_Version__ >= 599002000) 121 1.2 christos static kauth_listener_t ipf_listener; 122 1.2 christos #endif 123 1.2 christos 124 1.2 christos #if (__NetBSD_Version__ < 399001400) 125 1.2 christos extern int ip6_getpmtu (struct route_in6 *, struct route_in6 *, 126 1.2 christos struct ifnet *, struct in6_addr *, u_long *, 127 1.2 christos int *); 128 1.2 christos #endif 129 1.1 christos #if (NetBSD >= 199511) 130 1.1 christos static int ipfopen(dev_t dev, int flags, int devtype, PROC_T *p); 131 1.1 christos static int ipfclose(dev_t dev, int flags, int devtype, PROC_T *p); 132 1.1 christos #else 133 1.1 christos # if (__NetBSD_Version__ >= 399001400) 134 1.1 christos static int ipfopen(dev_t dev, int flags, struct lwp *); 135 1.1 christos static int ipfclose(dev_t dev, int flags, struct lwp *); 136 1.1 christos # else 137 1.1 christos static int ipfopen(dev_t dev, int flags); 138 1.1 christos static int ipfclose(dev_t dev, int flags); 139 1.1 christos # endif /* __NetBSD_Version__ >= 399001400 */ 140 1.1 christos #endif 141 1.1 christos static int ipfread(dev_t, struct uio *, int ioflag); 142 1.1 christos static int ipfwrite(dev_t, struct uio *, int ioflag); 143 1.1 christos static int ipfpoll(dev_t, int events, PROC_T *); 144 1.2 christos static void ipf_timer_func(void *ptr); 145 1.1 christos 146 1.1 christos const struct cdevsw ipl_cdevsw = { 147 1.8 dholland .d_open = ipfopen, 148 1.8 dholland .d_close = ipfclose, 149 1.8 dholland .d_read = ipfread, 150 1.8 dholland .d_write = ipfwrite, 151 1.8 dholland .d_ioctl = ipfioctl, 152 1.8 dholland .d_stop = nostop, 153 1.8 dholland .d_tty = notty, 154 1.8 dholland .d_poll = ipfpoll, 155 1.8 dholland .d_mmap = nommap, 156 1.1 christos #if (__NetBSD_Version__ >= 200000000) 157 1.8 dholland .d_kqfilter = nokqfilter, 158 1.1 christos #endif 159 1.11 dholland .d_discard = nodiscard, 160 1.1 christos #ifdef D_OTHER 161 1.8 dholland .d_flag = D_OTHER 162 1.39 mrg # if __NetBSD_Version__ >= 799003200 163 1.39 mrg | D_MPSAFE 164 1.39 mrg # endif 165 1.8 dholland #else 166 1.8 dholland .d_flag = 0 167 1.1 christos #endif 168 1.1 christos }; 169 1.13 pgoyette #if (__NetBSD_Version__ >= 799003000) 170 1.13 pgoyette kmutex_t ipf_ref_mutex; 171 1.13 pgoyette int ipf_active; 172 1.13 pgoyette #endif 173 1.1 christos 174 1.1 christos ipf_main_softc_t ipfmain; 175 1.1 christos 176 1.1 christos static u_short ipid = 0; 177 1.2 christos static int (*ipf_savep)(void *, ip_t *, int, void *, int, struct mbuf **); 178 1.2 christos static int ipf_send_ip(fr_info_t *, mb_t *); 179 1.1 christos #ifdef USE_INET6 180 1.2 christos static int ipf_fastroute6(struct mbuf *, struct mbuf **, 181 1.2 christos fr_info_t *, frdest_t *); 182 1.1 christos #endif 183 1.1 christos 184 1.1 christos #if defined(NETBSD_PF) 185 1.1 christos # include <net/pfil.h> 186 1.1 christos /* 187 1.1 christos * We provide the ipf_checkp name just to minimize changes later. 188 1.1 christos */ 189 1.2 christos int (*ipf_checkp)(void *, ip_t *ip, int hlen, void *ifp, int out, mb_t **mp); 190 1.1 christos #endif /* NETBSD_PF */ 191 1.1 christos 192 1.1 christos #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000) 193 1.1 christos # include <net/pfil.h> 194 1.1 christos 195 1.1 christos static int ipf_check_wrapper(void *, struct mbuf **, struct ifnet *, int ); 196 1.1 christos 197 1.1 christos static int 198 1.2 christos ipf_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) 199 1.1 christos { 200 1.1 christos struct ip *ip; 201 1.1 christos int rv, hlen; 202 1.1 christos 203 1.1 christos #if __NetBSD_Version__ >= 200080000 204 1.1 christos /* 205 1.1 christos * ensure that mbufs are writable beforehand 206 1.1 christos * as it's assumed by ipf code. 207 1.1 christos * XXX inefficient 208 1.1 christos */ 209 1.1 christos int error = m_makewritable(mp, 0, M_COPYALL, M_DONTWAIT); 210 1.1 christos 211 1.1 christos if (error) { 212 1.1 christos m_freem(*mp); 213 1.1 christos *mp = NULL; 214 1.1 christos return error; 215 1.1 christos } 216 1.1 christos #endif 217 1.1 christos ip = mtod(*mp, struct ip *); 218 1.1 christos hlen = ip->ip_hl << 2; 219 1.1 christos 220 1.1 christos #ifdef INET 221 1.1 christos #if defined(M_CSUM_TCPv4) 222 1.1 christos /* 223 1.1 christos * If the packet is out-bound, we can't delay checksums 224 1.1 christos * here. For in-bound, the checksum has already been 225 1.1 christos * validated. 226 1.1 christos */ 227 1.1 christos if (dir == PFIL_OUT) { 228 1.1 christos if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) { 229 1.29 maxv in_undefer_cksum_tcpudp(*mp); 230 1.1 christos (*mp)->m_pkthdr.csum_flags &= 231 1.1 christos ~(M_CSUM_TCPv4|M_CSUM_UDPv4); 232 1.1 christos } 233 1.1 christos } 234 1.1 christos #endif /* M_CSUM_TCPv4 */ 235 1.1 christos #endif /* INET */ 236 1.1 christos 237 1.1 christos /* 238 1.1 christos * Note, we don't need to update the checksum, because 239 1.1 christos * it has already been verified. 240 1.1 christos */ 241 1.1 christos rv = ipf_check(&ipfmain, ip, hlen, ifp, (dir == PFIL_OUT), mp); 242 1.1 christos 243 1.1 christos return (rv); 244 1.1 christos } 245 1.1 christos 246 1.1 christos # ifdef USE_INET6 247 1.1 christos # include <netinet/ip6.h> 248 1.1 christos 249 1.1 christos static int ipf_check_wrapper6(void *, struct mbuf **, struct ifnet *, int ); 250 1.1 christos 251 1.1 christos static int 252 1.2 christos ipf_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) 253 1.1 christos { 254 1.2 christos #if defined(INET6) 255 1.1 christos # if defined(M_CSUM_TCPv6) && (__NetBSD_Version__ > 200000000) 256 1.1 christos /* 257 1.1 christos * If the packet is out-bound, we can't delay checksums 258 1.1 christos * here. For in-bound, the checksum has already been 259 1.1 christos * validated. 260 1.1 christos */ 261 1.1 christos if (dir == PFIL_OUT) { 262 1.1 christos if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv6|M_CSUM_UDPv6)) { 263 1.1 christos # if (__NetBSD_Version__ > 399000600) 264 1.30 maxv in6_undefer_cksum_tcpudp(*mp); 265 1.1 christos # endif 266 1.1 christos (*mp)->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv6| 267 1.1 christos M_CSUM_UDPv6); 268 1.1 christos } 269 1.1 christos } 270 1.1 christos # endif 271 1.2 christos #endif /* INET6 */ 272 1.1 christos 273 1.1 christos return (ipf_check(&ipfmain, mtod(*mp, struct ip *), sizeof(struct ip6_hdr), 274 1.1 christos ifp, (dir == PFIL_OUT), mp)); 275 1.1 christos } 276 1.1 christos # endif 277 1.1 christos 278 1.1 christos 279 1.1 christos # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) 280 1.1 christos 281 1.20 christos # if (__NetBSD_Version__ >= 799000400) 282 1.20 christos 283 1.20 christos static void ipf_pfilsync(void *, unsigned long, void *); 284 1.20 christos 285 1.20 christos static void 286 1.20 christos ipf_pfilsync(void *hdr, unsigned long cmd, void *arg2) 287 1.1 christos { 288 1.1 christos /* 289 1.1 christos * The interface pointer is useless for create (we have nothing to 290 1.1 christos * compare it to) and at detach, the interface name is still in the 291 1.1 christos * list of active NICs (albeit, down, but that's not any real 292 1.1 christos * indicator) and doing ifunit() on the name will still return the 293 1.1 christos * pointer, so it's not much use then, either. 294 1.1 christos */ 295 1.1 christos ipf_sync(&ipfmain, NULL); 296 1.20 christos } 297 1.20 christos 298 1.20 christos # else 299 1.20 christos 300 1.20 christos static int ipf_pfilsync(void *, struct mbuf **, struct ifnet *, int); 301 1.20 christos 302 1.20 christos static int 303 1.20 christos ipf_pfilsync(void *hdr, struct mbuf **mp, struct ifnet *ifp, int dir) 304 1.20 christos { 305 1.20 christos ipf_sync(&ipfmain, NULL); 306 1.1 christos return 0; 307 1.1 christos } 308 1.20 christos 309 1.20 christos # endif 310 1.1 christos # endif 311 1.1 christos 312 1.1 christos #endif /* __NetBSD_Version__ >= 105110000 */ 313 1.1 christos 314 1.1 christos 315 1.1 christos #if defined(IPFILTER_LKM) 316 1.1 christos int 317 1.1 christos ipf_identify(s) 318 1.1 christos char *s; 319 1.1 christos { 320 1.1 christos if (strcmp(s, "ipl") == 0) 321 1.1 christos return 1; 322 1.1 christos return 0; 323 1.1 christos } 324 1.1 christos #endif /* IPFILTER_LKM */ 325 1.1 christos 326 1.2 christos #if (__NetBSD_Version__ >= 599002000) 327 1.2 christos static int 328 1.2 christos ipf_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, 329 1.2 christos void *arg0, void *arg1, void *arg2, void *arg3) 330 1.2 christos { 331 1.2 christos int result; 332 1.2 christos enum kauth_network_req req; 333 1.2 christos 334 1.2 christos result = KAUTH_RESULT_DEFER; 335 1.34 joerg req = (enum kauth_network_req)(uintptr_t)arg0; 336 1.2 christos 337 1.2 christos if (action != KAUTH_NETWORK_FIREWALL) 338 1.2 christos return result; 339 1.2 christos 340 1.2 christos /* These must have came from device context. */ 341 1.2 christos if ((req == KAUTH_REQ_NETWORK_FIREWALL_FW) || 342 1.2 christos (req == KAUTH_REQ_NETWORK_FIREWALL_NAT)) 343 1.2 christos result = KAUTH_RESULT_ALLOW; 344 1.2 christos 345 1.2 christos return result; 346 1.2 christos } 347 1.2 christos #endif 348 1.1 christos 349 1.1 christos /* 350 1.1 christos * Try to detect the case when compiling for NetBSD with pseudo-device 351 1.1 christos */ 352 1.1 christos void 353 1.2 christos ipfilterattach(int count) 354 1.1 christos { 355 1.2 christos 356 1.13 pgoyette #if (__NetBSD_Version__ >= 799003000) 357 1.13 pgoyette return; 358 1.13 pgoyette #else 359 1.2 christos #if (__NetBSD_Version__ >= 599002000) 360 1.2 christos ipf_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK, 361 1.2 christos ipf_listener_cb, NULL); 362 1.2 christos #endif 363 1.2 christos 364 1.1 christos if (ipf_load_all() == 0) 365 1.1 christos (void) ipf_create_all(&ipfmain); 366 1.13 pgoyette #endif 367 1.1 christos } 368 1.1 christos 369 1.1 christos 370 1.1 christos int 371 1.2 christos ipfattach(ipf_main_softc_t *softc) 372 1.1 christos { 373 1.1 christos SPL_INT(s); 374 1.1 christos #if (__NetBSD_Version__ >= 499005500) 375 1.1 christos int i; 376 1.1 christos #endif 377 1.1 christos #if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000) 378 1.1 christos int error = 0; 379 1.1 christos # if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000) 380 1.5 rmind pfil_head_t *ph_inet; 381 1.1 christos # ifdef USE_INET6 382 1.5 rmind pfil_head_t *ph_inet6; 383 1.1 christos # endif 384 1.1 christos # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) 385 1.5 rmind pfil_head_t *ph_ifsync; 386 1.1 christos # endif 387 1.1 christos # endif 388 1.1 christos #endif 389 1.1 christos 390 1.1 christos SPL_NET(s); 391 1.1 christos if ((softc->ipf_running > 0) || (ipf_checkp == ipf_check)) { 392 1.1 christos printf("IP Filter: already initialized\n"); 393 1.1 christos SPL_X(s); 394 1.1 christos IPFERROR(130017); 395 1.1 christos return EBUSY; 396 1.1 christos } 397 1.1 christos 398 1.1 christos if (ipf_init_all(softc) < 0) { 399 1.1 christos SPL_X(s); 400 1.1 christos IPFERROR(130015); 401 1.1 christos return EIO; 402 1.1 christos } 403 1.1 christos 404 1.1 christos #ifdef NETBSD_PF 405 1.1 christos # if (__NetBSD_Version__ >= 104200000) 406 1.1 christos # if __NetBSD_Version__ >= 105110000 407 1.5 rmind ph_inet = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET); 408 1.1 christos # ifdef USE_INET6 409 1.5 rmind ph_inet6 = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET6); 410 1.1 christos # endif 411 1.1 christos # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) 412 1.1 christos ph_ifsync = pfil_head_get(PFIL_TYPE_IFNET, 0); 413 1.1 christos # endif 414 1.1 christos 415 1.1 christos if (ph_inet == NULL 416 1.1 christos # ifdef USE_INET6 417 1.1 christos && ph_inet6 == NULL 418 1.1 christos # endif 419 1.1 christos # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) 420 1.1 christos && ph_ifsync == NULL 421 1.1 christos # endif 422 1.1 christos ) { 423 1.1 christos SPL_X(s); 424 1.1 christos IPFERROR(130016); 425 1.1 christos return ENODEV; 426 1.1 christos } 427 1.1 christos 428 1.1 christos if (ph_inet != NULL) 429 1.1 christos error = pfil_add_hook((void *)ipf_check_wrapper, NULL, 430 1.1 christos PFIL_IN|PFIL_OUT, ph_inet); 431 1.1 christos else 432 1.1 christos error = 0; 433 1.1 christos # else 434 1.1 christos error = pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, 435 1.1 christos &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); 436 1.1 christos # endif 437 1.1 christos if (error) { 438 1.1 christos IPFERROR(130013); 439 1.1 christos goto pfil_error; 440 1.1 christos } 441 1.1 christos # else 442 1.1 christos pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT); 443 1.1 christos # endif 444 1.1 christos 445 1.1 christos # ifdef USE_INET6 446 1.1 christos # if __NetBSD_Version__ >= 105110000 447 1.1 christos if (ph_inet6 != NULL) 448 1.1 christos error = pfil_add_hook((void *)ipf_check_wrapper6, NULL, 449 1.1 christos PFIL_IN|PFIL_OUT, ph_inet6); 450 1.1 christos else 451 1.1 christos error = 0; 452 1.1 christos if (error) { 453 1.1 christos pfil_remove_hook((void *)ipf_check_wrapper6, NULL, 454 1.1 christos PFIL_IN|PFIL_OUT, ph_inet6); 455 1.1 christos ipfmain.ipf_interror = 130014; 456 1.1 christos goto pfil_error; 457 1.1 christos } 458 1.1 christos # else 459 1.1 christos error = pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, 460 1.1 christos &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh); 461 1.1 christos if (error) { 462 1.1 christos pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, 463 1.1 christos &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); 464 1.1 christos IPFERROR(130014); 465 1.1 christos goto pfil_error; 466 1.1 christos } 467 1.1 christos # endif 468 1.1 christos # endif 469 1.1 christos 470 1.1 christos # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) 471 1.1 christos if (ph_ifsync != NULL) 472 1.20 christos #if (__NetBSD_Version__ >= 799000400) 473 1.21 christos (void) pfil_add_ihook((void *)ipf_pfilsync, NULL, 474 1.21 christos PFIL_IFNET, ph_ifsync); 475 1.20 christos #else 476 1.20 christos (void) pfil_add_hook((void *)ipf_pfilsync, NULL, 477 1.20 christos PFIL_IFNET, ph_ifsync); 478 1.20 christos #endif 479 1.1 christos # endif 480 1.1 christos #endif 481 1.1 christos 482 1.1 christos #if (__NetBSD_Version__ >= 499005500) 483 1.1 christos for (i = 0; i < IPL_LOGSIZE; i++) 484 1.1 christos selinit(&ipfmain.ipf_selwait[i]); 485 1.1 christos #else 486 1.1 christos bzero((char *)ipfmain.ipf_selwait, sizeof(ipfmain.ipf_selwait)); 487 1.1 christos #endif 488 1.1 christos ipf_savep = ipf_checkp; 489 1.1 christos ipf_checkp = ipf_check; 490 1.1 christos 491 1.1 christos #ifdef INET 492 1.1 christos if (softc->ipf_control_forwarding & 1) 493 1.1 christos ipforwarding = 1; 494 1.1 christos #endif 495 1.1 christos 496 1.1 christos ipid = 0; 497 1.1 christos 498 1.1 christos SPL_X(s); 499 1.1 christos 500 1.1 christos #if (__NetBSD_Version__ >= 104010000) 501 1.1 christos # if (__NetBSD_Version__ >= 499002000) 502 1.1 christos callout_init(&softc->ipf_slow_ch, 0); 503 1.1 christos # else 504 1.1 christos callout_init(&softc->ipf_slow_ch); 505 1.1 christos # endif 506 1.1 christos callout_reset(&softc->ipf_slow_ch, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT, 507 1.1 christos ipf_timer_func, softc); 508 1.1 christos #else 509 1.1 christos timeout(ipf_timer_func, softc, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); 510 1.1 christos #endif 511 1.2 christos 512 1.1 christos return 0; 513 1.1 christos 514 1.1 christos #if __NetBSD_Version__ >= 105110000 515 1.1 christos pfil_error: 516 1.1 christos SPL_X(s); 517 1.1 christos ipf_fini_all(softc); 518 1.1 christos return error; 519 1.1 christos #endif 520 1.1 christos } 521 1.1 christos 522 1.1 christos static void 523 1.2 christos ipf_timer_func(void *ptr) 524 1.1 christos { 525 1.1 christos ipf_main_softc_t *softc = ptr; 526 1.1 christos SPL_INT(s); 527 1.1 christos 528 1.1 christos SPL_NET(s); 529 1.1 christos READ_ENTER(&softc->ipf_global); 530 1.1 christos 531 1.1 christos if (softc->ipf_running > 0) 532 1.1 christos ipf_slowtimer(softc); 533 1.1 christos 534 1.1 christos if (softc->ipf_running == -1 || softc->ipf_running == 1) { 535 1.1 christos #if NETBSD_GE_REV(104240000) 536 1.1 christos callout_reset(&softc->ipf_slow_ch, hz / 2, 537 1.1 christos ipf_timer_func, softc); 538 1.1 christos #else 539 1.1 christos timeout(ipf_timer_func, softc, 540 1.1 christos (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); 541 1.1 christos #endif 542 1.1 christos } 543 1.1 christos RWLOCK_EXIT(&softc->ipf_global); 544 1.1 christos SPL_X(s); 545 1.1 christos } 546 1.1 christos 547 1.1 christos 548 1.1 christos /* 549 1.1 christos * Disable the filter by removing the hooks from the IP input/output 550 1.1 christos * stream. 551 1.1 christos */ 552 1.1 christos int 553 1.2 christos ipfdetach(ipf_main_softc_t *softc) 554 1.1 christos { 555 1.1 christos SPL_INT(s); 556 1.1 christos #if (__NetBSD_Version__ >= 499005500) 557 1.1 christos int i; 558 1.1 christos #endif 559 1.1 christos #if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000) 560 1.1 christos int error = 0; 561 1.1 christos # if __NetBSD_Version__ >= 105150000 562 1.5 rmind pfil_head_t *ph_inet = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET); 563 1.1 christos # ifdef USE_INET6 564 1.5 rmind pfil_head_t *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET6); 565 1.1 christos # endif 566 1.1 christos # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) 567 1.1 christos struct pfil_head *ph_ifsync = pfil_head_get(PFIL_TYPE_IFNET, 0); 568 1.1 christos # endif 569 1.1 christos # endif 570 1.1 christos #endif 571 1.1 christos 572 1.1 christos SPL_NET(s); 573 1.1 christos 574 1.1 christos #if (__NetBSD_Version__ >= 104010000) 575 1.1 christos if (softc->ipf_running > 0) 576 1.1 christos callout_stop(&softc->ipf_slow_ch); 577 1.1 christos #else 578 1.1 christos untimeout(ipf_slowtimer, NULL); 579 1.1 christos #endif /* NetBSD */ 580 1.1 christos 581 1.1 christos ipf_checkp = ipf_savep; 582 1.1 christos (void) ipf_flush(softc, IPL_LOGIPF, FR_INQUE|FR_OUTQUE|FR_INACTIVE); 583 1.1 christos (void) ipf_flush(softc, IPL_LOGIPF, FR_INQUE|FR_OUTQUE); 584 1.1 christos 585 1.1 christos #ifdef INET 586 1.1 christos if (softc->ipf_control_forwarding & 2) 587 1.1 christos ipforwarding = 0; 588 1.1 christos #endif 589 1.1 christos 590 1.1 christos #ifdef NETBSD_PF 591 1.1 christos # if (__NetBSD_Version__ >= 104200000) 592 1.1 christos # if __NetBSD_Version__ >= 105110000 593 1.1 christos # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) 594 1.23 christos # if __NetBSD_Version__ >= 799000400 595 1.23 christos (void) pfil_remove_ihook((void *)ipf_pfilsync, NULL, 596 1.23 christos PFIL_IFNET, ph_ifsync); 597 1.23 christos # else 598 1.1 christos (void) pfil_remove_hook((void *)ipf_pfilsync, NULL, 599 1.1 christos PFIL_IFNET, ph_ifsync); 600 1.23 christos # endif 601 1.1 christos # endif 602 1.1 christos 603 1.1 christos if (ph_inet != NULL) 604 1.1 christos error = pfil_remove_hook((void *)ipf_check_wrapper, NULL, 605 1.1 christos PFIL_IN|PFIL_OUT, ph_inet); 606 1.1 christos else 607 1.1 christos error = 0; 608 1.1 christos # else 609 1.1 christos error = pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, 610 1.1 christos &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); 611 1.1 christos # endif 612 1.1 christos if (error) { 613 1.1 christos SPL_X(s); 614 1.1 christos IPFERROR(130011); 615 1.1 christos return error; 616 1.1 christos } 617 1.1 christos # else 618 1.1 christos pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT); 619 1.1 christos # endif 620 1.1 christos # ifdef USE_INET6 621 1.1 christos # if __NetBSD_Version__ >= 105110000 622 1.1 christos if (ph_inet6 != NULL) 623 1.1 christos error = pfil_remove_hook((void *)ipf_check_wrapper6, NULL, 624 1.1 christos PFIL_IN|PFIL_OUT, ph_inet6); 625 1.1 christos else 626 1.1 christos error = 0; 627 1.1 christos # else 628 1.1 christos error = pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, 629 1.1 christos &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh); 630 1.1 christos # endif 631 1.1 christos if (error) { 632 1.1 christos SPL_X(s); 633 1.1 christos IPFERROR(130012); 634 1.1 christos return error; 635 1.1 christos } 636 1.1 christos # endif 637 1.1 christos #endif 638 1.1 christos SPL_X(s); 639 1.1 christos 640 1.1 christos #if (__NetBSD_Version__ >= 499005500) 641 1.1 christos for (i = 0; i < IPL_LOGSIZE; i++) 642 1.1 christos seldestroy(&ipfmain.ipf_selwait[i]); 643 1.1 christos #endif 644 1.1 christos 645 1.1 christos ipf_fini_all(softc); 646 1.1 christos 647 1.1 christos return 0; 648 1.1 christos } 649 1.1 christos 650 1.1 christos 651 1.1 christos /* 652 1.1 christos * Filter ioctl interface. 653 1.1 christos */ 654 1.1 christos int 655 1.2 christos ipfioctl(dev_t dev, u_long cmd, 656 1.2 christos #if (__NetBSD_Version__ >= 499001000) 657 1.2 christos void *data, 658 1.2 christos #else 659 1.2 christos caddr_t data, 660 1.2 christos #endif 661 1.2 christos int mode 662 1.1 christos #if (NetBSD >= 199511) 663 1.1 christos # if (__NetBSD_Version__ >= 399001400) 664 1.2 christos , struct lwp *p 665 1.1 christos # if (__NetBSD_Version__ >= 399002000) 666 1.1 christos # define UID(l) kauth_cred_getuid((l)->l_cred) 667 1.1 christos # else 668 1.1 christos # define UID(l) ((l)->l_proc->p_cred->p_ruid) 669 1.1 christos # endif 670 1.1 christos # else 671 1.2 christos , struct proc *p 672 1.1 christos # define UID(p) ((p)->p_cred->p_ruid) 673 1.1 christos # endif 674 1.2 christos #endif 675 1.1 christos ) 676 1.1 christos { 677 1.1 christos int error = 0, unit = 0; 678 1.1 christos SPL_INT(s); 679 1.1 christos 680 1.1 christos #if (__NetBSD_Version__ >= 399002000) 681 1.1 christos if ((mode & FWRITE) && 682 1.1 christos kauth_authorize_network(p->l_cred, KAUTH_NETWORK_FIREWALL, 683 1.1 christos KAUTH_REQ_NETWORK_FIREWALL_FW, NULL, 684 1.1 christos NULL, NULL)) { 685 1.1 christos ipfmain.ipf_interror = 130005; 686 1.1 christos return EPERM; 687 1.1 christos } 688 1.1 christos #else 689 1.1 christos if ((securelevel >= 2) && (mode & FWRITE)) { 690 1.1 christos ipfmain.ipf_interror = 130001; 691 1.1 christos return EPERM; 692 1.1 christos } 693 1.1 christos #endif 694 1.1 christos 695 1.1 christos unit = GET_MINOR(dev); 696 1.1 christos if ((IPL_LOGMAX < unit) || (unit < 0)) { 697 1.1 christos ipfmain.ipf_interror = 130002; 698 1.1 christos return ENXIO; 699 1.1 christos } 700 1.1 christos 701 1.1 christos if (ipfmain.ipf_running <= 0) { 702 1.2 christos if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) { 703 1.1 christos ipfmain.ipf_interror = 130003; 704 1.1 christos return EIO; 705 1.1 christos } 706 1.1 christos if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && 707 1.1 christos cmd != SIOCIPFSET && cmd != SIOCFRENB && 708 1.1 christos cmd != SIOCGETFS && cmd != SIOCGETFF && 709 1.1 christos cmd != SIOCIPFINTERROR) { 710 1.1 christos ipfmain.ipf_interror = 130004; 711 1.1 christos return EIO; 712 1.1 christos } 713 1.1 christos } 714 1.1 christos 715 1.1 christos SPL_NET(s); 716 1.1 christos 717 1.1 christos error = ipf_ioctlswitch(&ipfmain, unit, data, cmd, mode, UID(p), p); 718 1.1 christos if (error != -1) { 719 1.1 christos SPL_X(s); 720 1.1 christos return error; 721 1.1 christos } 722 1.1 christos 723 1.1 christos SPL_X(s); 724 1.1 christos return error; 725 1.1 christos } 726 1.1 christos 727 1.1 christos 728 1.1 christos /* 729 1.1 christos * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that 730 1.1 christos * requires a large amount of setting up and isn't any more efficient. 731 1.1 christos */ 732 1.1 christos int 733 1.2 christos ipf_send_reset(fr_info_t *fin) 734 1.1 christos { 735 1.1 christos struct tcphdr *tcp, *tcp2; 736 1.1 christos int tlen = 0, hlen; 737 1.1 christos struct mbuf *m; 738 1.1 christos #ifdef USE_INET6 739 1.1 christos ip6_t *ip6; 740 1.1 christos #endif 741 1.1 christos ip_t *ip; 742 1.1 christos 743 1.1 christos tcp = fin->fin_dp; 744 1.1 christos if (tcp->th_flags & TH_RST) 745 1.1 christos return -1; /* feedback loop */ 746 1.1 christos 747 1.1 christos if (ipf_checkl4sum(fin) == -1) 748 1.1 christos return -1; 749 1.1 christos 750 1.1 christos tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) + 751 1.1 christos ((tcp->th_flags & TH_SYN) ? 1 : 0) + 752 1.1 christos ((tcp->th_flags & TH_FIN) ? 1 : 0); 753 1.1 christos 754 1.1 christos #ifdef USE_INET6 755 1.1 christos hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t); 756 1.1 christos #else 757 1.1 christos hlen = sizeof(ip_t); 758 1.1 christos #endif 759 1.1 christos #ifdef MGETHDR 760 1.1 christos MGETHDR(m, M_DONTWAIT, MT_HEADER); 761 1.1 christos #else 762 1.1 christos MGET(m, M_DONTWAIT, MT_HEADER); 763 1.1 christos #endif 764 1.1 christos if (m == NULL) 765 1.1 christos return -1; 766 1.1 christos if (sizeof(*tcp2) + hlen > MHLEN) { 767 1.1 christos MCLGET(m, M_DONTWAIT); 768 1.1 christos if (m == NULL) 769 1.1 christos return -1; 770 1.1 christos if ((m->m_flags & M_EXT) == 0) { 771 1.1 christos FREE_MB_T(m); 772 1.1 christos return -1; 773 1.1 christos } 774 1.1 christos } 775 1.1 christos 776 1.1 christos m->m_len = sizeof(*tcp2) + hlen; 777 1.1 christos m->m_data += max_linkhdr; 778 1.1 christos m->m_pkthdr.len = m->m_len; 779 1.14 ozaki m_reset_rcvif(m); 780 1.1 christos ip = mtod(m, struct ip *); 781 1.1 christos bzero((char *)ip, hlen); 782 1.1 christos #ifdef USE_INET6 783 1.1 christos ip6 = (ip6_t *)ip; 784 1.1 christos #endif 785 1.1 christos bzero((char *)ip, sizeof(*tcp2) + hlen); 786 1.1 christos tcp2 = (struct tcphdr *)((char *)ip + hlen); 787 1.1 christos tcp2->th_sport = tcp->th_dport; 788 1.1 christos tcp2->th_dport = tcp->th_sport; 789 1.1 christos 790 1.1 christos if (tcp->th_flags & TH_ACK) { 791 1.1 christos tcp2->th_seq = tcp->th_ack; 792 1.1 christos tcp2->th_flags = TH_RST; 793 1.1 christos tcp2->th_ack = 0; 794 1.1 christos } else { 795 1.1 christos tcp2->th_seq = 0; 796 1.1 christos tcp2->th_ack = ntohl(tcp->th_seq); 797 1.1 christos tcp2->th_ack += tlen; 798 1.1 christos tcp2->th_ack = htonl(tcp2->th_ack); 799 1.1 christos tcp2->th_flags = TH_RST|TH_ACK; 800 1.1 christos } 801 1.1 christos tcp2->th_x2 = 0; 802 1.1 christos TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2); 803 1.1 christos tcp2->th_win = tcp->th_win; 804 1.1 christos tcp2->th_sum = 0; 805 1.1 christos tcp2->th_urp = 0; 806 1.1 christos 807 1.1 christos #ifdef USE_INET6 808 1.1 christos if (fin->fin_v == 6) { 809 1.1 christos ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; 810 1.1 christos ip6->ip6_plen = htons(sizeof(struct tcphdr)); 811 1.1 christos ip6->ip6_nxt = IPPROTO_TCP; 812 1.1 christos ip6->ip6_hlim = 0; 813 1.1 christos ip6->ip6_src = fin->fin_dst6.in6; 814 1.1 christos ip6->ip6_dst = fin->fin_src6.in6; 815 1.1 christos tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, 816 1.1 christos sizeof(*ip6), sizeof(*tcp2)); 817 1.1 christos return ipf_send_ip(fin, m); 818 1.1 christos } 819 1.1 christos #endif 820 1.1 christos #ifdef INET 821 1.1 christos ip->ip_p = IPPROTO_TCP; 822 1.1 christos ip->ip_len = htons(sizeof(struct tcphdr)); 823 1.1 christos ip->ip_src.s_addr = fin->fin_daddr; 824 1.1 christos ip->ip_dst.s_addr = fin->fin_saddr; 825 1.1 christos tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); 826 1.1 christos ip->ip_len = hlen + sizeof(*tcp2); 827 1.1 christos return ipf_send_ip(fin, m); 828 1.1 christos #else 829 1.1 christos return 0; 830 1.1 christos #endif 831 1.1 christos } 832 1.1 christos 833 1.1 christos 834 1.1 christos /* 835 1.1 christos * Expects ip_len to be in host byte order when called. 836 1.1 christos */ 837 1.1 christos static int 838 1.2 christos ipf_send_ip(fr_info_t *fin, mb_t *m) 839 1.1 christos { 840 1.1 christos fr_info_t fnew; 841 1.1 christos #ifdef INET 842 1.1 christos ip_t *oip; 843 1.1 christos #endif 844 1.1 christos ip_t *ip; 845 1.1 christos int hlen; 846 1.1 christos 847 1.1 christos ip = mtod(m, ip_t *); 848 1.1 christos bzero((char *)&fnew, sizeof(fnew)); 849 1.1 christos fnew.fin_main_soft = fin->fin_main_soft; 850 1.1 christos 851 1.1 christos IP_V_A(ip, fin->fin_v); 852 1.1 christos switch (fin->fin_v) 853 1.1 christos { 854 1.1 christos #ifdef INET 855 1.1 christos case 4 : 856 1.1 christos oip = fin->fin_ip; 857 1.1 christos hlen = sizeof(*oip); 858 1.1 christos fnew.fin_v = 4; 859 1.1 christos fnew.fin_p = ip->ip_p; 860 1.1 christos fnew.fin_plen = ntohs(ip->ip_len); 861 1.1 christos HTONS(ip->ip_len); 862 1.1 christos IP_HL_A(ip, sizeof(*oip) >> 2); 863 1.1 christos ip->ip_tos = oip->ip_tos; 864 1.1 christos ip->ip_id = ipf_nextipid(fin); 865 1.1 christos ip->ip_off = htons(ip_mtudisc ? IP_DF : 0); 866 1.1 christos ip->ip_ttl = ip_defttl; 867 1.1 christos ip->ip_sum = 0; 868 1.1 christos break; 869 1.1 christos #endif 870 1.1 christos #ifdef USE_INET6 871 1.1 christos case 6 : 872 1.1 christos { 873 1.1 christos ip6_t *ip6 = (ip6_t *)ip; 874 1.1 christos 875 1.1 christos ip6->ip6_vfc = 0x60; 876 1.1 christos ip6->ip6_hlim = IPDEFTTL; 877 1.1 christos 878 1.1 christos hlen = sizeof(*ip6); 879 1.1 christos fnew.fin_p = ip6->ip6_nxt; 880 1.1 christos fnew.fin_v = 6; 881 1.1 christos fnew.fin_plen = ntohs(ip6->ip6_plen) + hlen; 882 1.1 christos break; 883 1.1 christos } 884 1.1 christos #endif 885 1.1 christos default : 886 1.1 christos return EINVAL; 887 1.1 christos } 888 1.2 christos #ifdef KAME_IPSEC 889 1.14 ozaki m_reset_rcvif(m); 890 1.1 christos #endif 891 1.1 christos 892 1.1 christos fnew.fin_ifp = fin->fin_ifp; 893 1.1 christos fnew.fin_flx = FI_NOCKSUM; 894 1.1 christos fnew.fin_m = m; 895 1.1 christos fnew.fin_ip = ip; 896 1.1 christos fnew.fin_mp = &m; 897 1.1 christos fnew.fin_hlen = hlen; 898 1.1 christos fnew.fin_dp = (char *)ip + hlen; 899 1.1 christos (void) ipf_makefrip(hlen, ip, &fnew); 900 1.1 christos 901 1.1 christos return ipf_fastroute(m, &m, &fnew, NULL); 902 1.1 christos } 903 1.1 christos 904 1.1 christos 905 1.1 christos int 906 1.2 christos ipf_send_icmp_err(int type, fr_info_t *fin, int dst) 907 1.1 christos { 908 1.7 mrg int err, hlen, xtra, iclen, ohlen, avail; 909 1.1 christos struct in_addr dst4; 910 1.1 christos struct icmp *icmp; 911 1.1 christos struct mbuf *m; 912 1.1 christos i6addr_t dst6; 913 1.1 christos void *ifp; 914 1.1 christos #ifdef USE_INET6 915 1.7 mrg int code; 916 1.1 christos ip6_t *ip6; 917 1.1 christos #endif 918 1.1 christos ip_t *ip, *ip2; 919 1.1 christos 920 1.1 christos if ((type < 0) || (type > ICMP_MAXTYPE)) 921 1.1 christos return -1; 922 1.1 christos 923 1.7 mrg #ifdef USE_INET6 924 1.1 christos code = fin->fin_icode; 925 1.4 msaitoh if ((code < 0) || (code >= sizeof(icmptoicmp6unreach)/sizeof(int))) 926 1.1 christos return -1; 927 1.1 christos #endif 928 1.1 christos 929 1.1 christos if (ipf_checkl4sum(fin) == -1) 930 1.1 christos return -1; 931 1.1 christos #ifdef MGETHDR 932 1.1 christos MGETHDR(m, M_DONTWAIT, MT_HEADER); 933 1.1 christos #else 934 1.1 christos MGET(m, M_DONTWAIT, MT_HEADER); 935 1.1 christos #endif 936 1.1 christos if (m == NULL) 937 1.1 christos return -1; 938 1.1 christos avail = MHLEN; 939 1.1 christos 940 1.1 christos xtra = 0; 941 1.1 christos hlen = 0; 942 1.1 christos ohlen = 0; 943 1.1 christos dst4.s_addr = 0; 944 1.1 christos ifp = fin->fin_ifp; 945 1.1 christos if (fin->fin_v == 4) { 946 1.1 christos if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) 947 1.1 christos switch (ntohs(fin->fin_data[0]) >> 8) 948 1.1 christos { 949 1.1 christos case ICMP_ECHO : 950 1.1 christos case ICMP_TSTAMP : 951 1.1 christos case ICMP_IREQ : 952 1.1 christos case ICMP_MASKREQ : 953 1.1 christos break; 954 1.1 christos default : 955 1.1 christos FREE_MB_T(m); 956 1.1 christos return 0; 957 1.1 christos } 958 1.1 christos 959 1.1 christos if (dst == 0) { 960 1.1 christos if (ipf_ifpaddr(&ipfmain, 4, FRI_NORMAL, ifp, 961 1.1 christos &dst6, NULL) == -1) { 962 1.1 christos FREE_MB_T(m); 963 1.1 christos return -1; 964 1.1 christos } 965 1.1 christos dst4 = dst6.in4; 966 1.1 christos } else 967 1.1 christos dst4.s_addr = fin->fin_daddr; 968 1.1 christos 969 1.1 christos hlen = sizeof(ip_t); 970 1.1 christos ohlen = fin->fin_hlen; 971 1.1 christos iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; 972 1.1 christos if (fin->fin_hlen < fin->fin_plen) 973 1.1 christos xtra = MIN(fin->fin_dlen, 8); 974 1.1 christos else 975 1.1 christos xtra = 0; 976 1.1 christos } 977 1.1 christos 978 1.1 christos #ifdef USE_INET6 979 1.1 christos else if (fin->fin_v == 6) { 980 1.1 christos hlen = sizeof(ip6_t); 981 1.1 christos ohlen = sizeof(ip6_t); 982 1.1 christos iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; 983 1.1 christos type = icmptoicmp6types[type]; 984 1.1 christos if (type == ICMP6_DST_UNREACH) 985 1.1 christos code = icmptoicmp6unreach[code]; 986 1.1 christos 987 1.1 christos if (iclen + max_linkhdr + fin->fin_plen > avail) { 988 1.1 christos MCLGET(m, M_DONTWAIT); 989 1.1 christos if (m == NULL) 990 1.1 christos return -1; 991 1.1 christos if ((m->m_flags & M_EXT) == 0) { 992 1.1 christos FREE_MB_T(m); 993 1.1 christos return -1; 994 1.1 christos } 995 1.1 christos avail = MCLBYTES; 996 1.1 christos } 997 1.1 christos xtra = MIN(fin->fin_plen, avail - iclen - max_linkhdr); 998 1.1 christos xtra = MIN(xtra, IPV6_MMTU - iclen); 999 1.25 christos if (dst == 0 && !IN6_IS_ADDR_LINKLOCAL(&fin->fin_dst6.in6)) { 1000 1.1 christos if (ipf_ifpaddr(&ipfmain, 6, FRI_NORMAL, ifp, 1001 1.1 christos &dst6, NULL) == -1) { 1002 1.1 christos FREE_MB_T(m); 1003 1.1 christos return -1; 1004 1.1 christos } 1005 1.1 christos } else 1006 1.1 christos dst6 = fin->fin_dst6; 1007 1.1 christos } 1008 1.1 christos #endif 1009 1.1 christos else { 1010 1.1 christos FREE_MB_T(m); 1011 1.1 christos return -1; 1012 1.1 christos } 1013 1.1 christos 1014 1.1 christos avail -= (max_linkhdr + iclen); 1015 1.1 christos if (avail < 0) { 1016 1.1 christos FREE_MB_T(m); 1017 1.1 christos return -1; 1018 1.1 christos } 1019 1.1 christos if (xtra > avail) 1020 1.1 christos xtra = avail; 1021 1.1 christos iclen += xtra; 1022 1.1 christos m->m_data += max_linkhdr; 1023 1.14 ozaki m_reset_rcvif(m); 1024 1.1 christos m->m_pkthdr.len = iclen; 1025 1.1 christos m->m_len = iclen; 1026 1.1 christos ip = mtod(m, ip_t *); 1027 1.1 christos icmp = (struct icmp *)((char *)ip + hlen); 1028 1.1 christos ip2 = (ip_t *)&icmp->icmp_ip; 1029 1.1 christos 1030 1.1 christos icmp->icmp_type = type; 1031 1.1 christos icmp->icmp_code = fin->fin_icode; 1032 1.1 christos icmp->icmp_cksum = 0; 1033 1.1 christos #ifdef icmp_nextmtu 1034 1.1 christos if (type == ICMP_UNREACH && fin->fin_icode == ICMP_UNREACH_NEEDFRAG) { 1035 1.1 christos if (fin->fin_mtu != 0) { 1036 1.1 christos icmp->icmp_nextmtu = htons(fin->fin_mtu); 1037 1.1 christos 1038 1.1 christos } else if (ifp != NULL) { 1039 1.1 christos icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp)); 1040 1.1 christos 1041 1.1 christos } else { /* make up a number... */ 1042 1.1 christos icmp->icmp_nextmtu = htons(fin->fin_plen - 20); 1043 1.1 christos } 1044 1.1 christos } 1045 1.1 christos #endif 1046 1.1 christos 1047 1.1 christos bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); 1048 1.1 christos 1049 1.1 christos #if defined(M_CSUM_IPv4) 1050 1.1 christos /* 1051 1.1 christos * Clear any in-bound checksum flags for this packet. 1052 1.1 christos */ 1053 1.1 christos m->m_pkthdr.csuminfo = 0; 1054 1.1 christos #endif /* __NetBSD__ && M_CSUM_IPv4 */ 1055 1.1 christos 1056 1.1 christos #ifdef USE_INET6 1057 1.1 christos ip6 = (ip6_t *)ip; 1058 1.1 christos if (fin->fin_v == 6) { 1059 1.1 christos ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; 1060 1.1 christos ip6->ip6_plen = htons(iclen - hlen); 1061 1.1 christos ip6->ip6_nxt = IPPROTO_ICMPV6; 1062 1.1 christos ip6->ip6_hlim = 0; 1063 1.1 christos ip6->ip6_src = dst6.in6; 1064 1.1 christos ip6->ip6_dst = fin->fin_src6.in6; 1065 1.1 christos if (xtra > 0) 1066 1.1 christos bcopy((char *)fin->fin_ip + ohlen, 1067 1.1 christos (char *)&icmp->icmp_ip + ohlen, xtra); 1068 1.1 christos icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6, 1069 1.1 christos sizeof(*ip6), iclen - hlen); 1070 1.1 christos } else 1071 1.1 christos #endif 1072 1.1 christos { 1073 1.1 christos ip->ip_p = IPPROTO_ICMP; 1074 1.1 christos ip->ip_src.s_addr = dst4.s_addr; 1075 1.1 christos ip->ip_dst.s_addr = fin->fin_saddr; 1076 1.1 christos 1077 1.1 christos if (xtra > 0) 1078 1.1 christos bcopy((char *)fin->fin_ip + ohlen, 1079 1.1 christos (char *)&icmp->icmp_ip + ohlen, xtra); 1080 1.1 christos icmp->icmp_cksum = ipf_cksum((u_short *)icmp, 1081 1.1 christos sizeof(*icmp) + 8); 1082 1.1 christos ip->ip_len = iclen; 1083 1.1 christos ip->ip_p = IPPROTO_ICMP; 1084 1.1 christos } 1085 1.1 christos err = ipf_send_ip(fin, m); 1086 1.1 christos return err; 1087 1.1 christos } 1088 1.1 christos 1089 1.1 christos 1090 1.1 christos /* 1091 1.1 christos * m0 - pointer to mbuf where the IP packet starts 1092 1.1 christos * mpp - pointer to the mbuf pointer that is the start of the mbuf chain 1093 1.1 christos */ 1094 1.1 christos int 1095 1.2 christos ipf_fastroute(mb_t *m0, mb_t **mpp, fr_info_t *fin, frdest_t *fdp) 1096 1.1 christos { 1097 1.1 christos register struct ip *ip, *mhip; 1098 1.1 christos register struct mbuf *m = *mpp; 1099 1.1 christos register struct route *ro; 1100 1.1 christos int len, off, error = 0, hlen, code; 1101 1.1 christos struct ifnet *ifp, *sifp; 1102 1.1 christos ipf_main_softc_t *softc; 1103 1.1 christos #if __NetBSD_Version__ >= 499001100 1104 1.1 christos union { 1105 1.1 christos struct sockaddr dst; 1106 1.1 christos struct sockaddr_in dst4; 1107 1.1 christos } u; 1108 1.1 christos #else 1109 1.1 christos struct sockaddr_in *dst4; 1110 1.1 christos #endif 1111 1.1 christos struct sockaddr *dst; 1112 1.1 christos u_short ip_off, ip_len; 1113 1.1 christos struct route iproute; 1114 1.1 christos struct rtentry *rt; 1115 1.1 christos frdest_t node; 1116 1.1 christos frentry_t *fr; 1117 1.1 christos 1118 1.1 christos if (fin->fin_v == 6) { 1119 1.1 christos #ifdef USE_INET6 1120 1.1 christos error = ipf_fastroute6(m0, mpp, fin, fdp); 1121 1.1 christos #else 1122 1.1 christos error = EPROTONOSUPPORT; 1123 1.1 christos #endif 1124 1.1 christos if ((error != 0) && (*mpp != NULL)) 1125 1.1 christos FREE_MB_T(*mpp); 1126 1.1 christos return error; 1127 1.1 christos } 1128 1.1 christos #ifndef INET 1129 1.1 christos FREE_MB_T(*mpp); 1130 1.1 christos return EPROTONOSUPPORT; 1131 1.1 christos #else 1132 1.1 christos 1133 1.1 christos hlen = fin->fin_hlen; 1134 1.1 christos ip = mtod(m0, struct ip *); 1135 1.1 christos softc = fin->fin_main_soft; 1136 1.1 christos rt = NULL; 1137 1.1 christos ifp = NULL; 1138 1.1 christos 1139 1.1 christos # if defined(M_CSUM_IPv4) 1140 1.1 christos /* 1141 1.1 christos * Clear any in-bound checksum flags for this packet. 1142 1.1 christos */ 1143 1.1 christos m0->m_pkthdr.csuminfo = 0; 1144 1.1 christos # endif /* __NetBSD__ && M_CSUM_IPv4 */ 1145 1.1 christos 1146 1.1 christos /* 1147 1.1 christos * Route packet. 1148 1.1 christos */ 1149 1.1 christos ro = &iproute; 1150 1.2 christos memset(ro, 0, sizeof(*ro)); 1151 1.1 christos fr = fin->fin_fr; 1152 1.1 christos 1153 1.1 christos if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && 1154 1.1 christos (fdp->fd_type == FRD_DSTLIST)) { 1155 1.1 christos if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) 1156 1.1 christos fdp = &node; 1157 1.1 christos } 1158 1.1 christos if (fdp != NULL) 1159 1.1 christos ifp = fdp->fd_ptr; 1160 1.1 christos else 1161 1.1 christos ifp = fin->fin_ifp; 1162 1.1 christos 1163 1.1 christos if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) { 1164 1.1 christos error = -2; 1165 1.1 christos goto bad; 1166 1.1 christos } 1167 1.1 christos 1168 1.1 christos # if __NetBSD_Version__ >= 499001100 1169 1.1 christos if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) 1170 1.1 christos sockaddr_in_init(&u.dst4, &fdp->fd_ip, 0); 1171 1.1 christos else 1172 1.1 christos sockaddr_in_init(&u.dst4, &ip->ip_dst, 0); 1173 1.1 christos dst = &u.dst; 1174 1.1 christos rtcache_setdst(ro, dst); 1175 1.1 christos rt = rtcache_init(ro); 1176 1.1 christos # else 1177 1.1 christos dst4 = (struct sockaddr_in *)&ro->ro_dst; 1178 1.1 christos dst = (struct sockaddr *)dst4; 1179 1.1 christos dst4->sin_family = AF_INET; 1180 1.1 christos dst4->sin_addr = ip->ip_dst; 1181 1.1 christos 1182 1.1 christos if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) 1183 1.1 christos dst4->sin_addr = fdp->fd_ip; 1184 1.1 christos 1185 1.1 christos dst4->sin_len = sizeof(*dst); 1186 1.1 christos rtalloc(ro); 1187 1.1 christos rt = ro->ro_rt; 1188 1.1 christos # endif 1189 1.1 christos if ((ifp == NULL) && (rt != NULL)) 1190 1.1 christos ifp = rt->rt_ifp; 1191 1.1 christos if ((rt == NULL) || (ifp == NULL)) { 1192 1.2 christos #ifdef INET 1193 1.1 christos if (in_localaddr(ip->ip_dst)) 1194 1.1 christos error = EHOSTUNREACH; 1195 1.1 christos else 1196 1.2 christos #endif 1197 1.1 christos error = ENETUNREACH; 1198 1.1 christos goto bad; 1199 1.1 christos } 1200 1.1 christos 1201 1.1 christos 1202 1.1 christos if (rt->rt_flags & RTF_GATEWAY) 1203 1.1 christos dst = rt->rt_gateway; 1204 1.1 christos 1205 1.1 christos rt->rt_use++; 1206 1.1 christos 1207 1.1 christos /* 1208 1.1 christos * For input packets which are being "fastrouted", they won't 1209 1.1 christos * go back through output filtering and miss their chance to get 1210 1.1 christos * NAT'd and counted. Duplicated packets aren't considered to be 1211 1.1 christos * part of the normal packet stream, so do not NAT them or pass 1212 1.1 christos * them through stateful checking, etc. 1213 1.1 christos */ 1214 1.1 christos if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) { 1215 1.1 christos sifp = fin->fin_ifp; 1216 1.1 christos fin->fin_ifp = ifp; 1217 1.1 christos fin->fin_out = 1; 1218 1.1 christos (void) ipf_acctpkt(fin, NULL); 1219 1.1 christos fin->fin_fr = NULL; 1220 1.1 christos if (!fr || !(fr->fr_flags & FR_RETMASK)) { 1221 1.1 christos u_32_t pass; 1222 1.1 christos 1223 1.1 christos (void) ipf_state_check(fin, &pass); 1224 1.1 christos } 1225 1.1 christos 1226 1.1 christos switch (ipf_nat_checkout(fin, NULL)) 1227 1.1 christos { 1228 1.1 christos case 0 : 1229 1.1 christos break; 1230 1.1 christos case 1 : 1231 1.1 christos ip->ip_sum = 0; 1232 1.1 christos break; 1233 1.1 christos case -1 : 1234 1.1 christos error = -1; 1235 1.1 christos goto bad; 1236 1.1 christos break; 1237 1.1 christos } 1238 1.1 christos 1239 1.1 christos fin->fin_ifp = sifp; 1240 1.1 christos fin->fin_out = 0; 1241 1.1 christos } else 1242 1.1 christos ip->ip_sum = 0; 1243 1.1 christos /* 1244 1.1 christos * If small enough for interface, can just send directly. 1245 1.1 christos */ 1246 1.14 ozaki m_set_rcvif(m, ifp); 1247 1.1 christos 1248 1.1 christos ip_len = ntohs(ip->ip_len); 1249 1.1 christos if (ip_len <= ifp->if_mtu) { 1250 1.1 christos # if defined(M_CSUM_IPv4) 1251 1.1 christos # if (__NetBSD_Version__ >= 105009999) 1252 1.1 christos if (ifp->if_csum_flags_tx & M_CSUM_IPv4) 1253 1.1 christos m->m_pkthdr.csuminfo |= M_CSUM_IPv4; 1254 1.1 christos # else 1255 1.1 christos if (ifp->if_capabilities & IFCAP_CSUM_IPv4) 1256 1.1 christos m->m_pkthdr.csuminfo |= M_CSUM_IPv4; 1257 1.1 christos # endif /* (__NetBSD_Version__ >= 105009999) */ 1258 1.1 christos else if (ip->ip_sum == 0) 1259 1.1 christos ip->ip_sum = in_cksum(m, hlen); 1260 1.1 christos # else 1261 1.1 christos if (!ip->ip_sum) 1262 1.1 christos ip->ip_sum = in_cksum(m, hlen); 1263 1.1 christos # endif /* M_CSUM_IPv4 */ 1264 1.1 christos 1265 1.15 knakahar error = if_output_lock(ifp, ifp, m, dst, rt); 1266 1.1 christos goto done; 1267 1.1 christos } 1268 1.1 christos 1269 1.1 christos /* 1270 1.1 christos * Too large for interface; fragment if possible. 1271 1.1 christos * Must be able to put at least 8 bytes per fragment. 1272 1.1 christos */ 1273 1.1 christos ip_off = ntohs(ip->ip_off); 1274 1.1 christos if (ip_off & IP_DF) { 1275 1.1 christos error = EMSGSIZE; 1276 1.1 christos goto bad; 1277 1.1 christos } 1278 1.1 christos len = (ifp->if_mtu - hlen) &~ 7; 1279 1.1 christos if (len < 8) { 1280 1.1 christos error = EMSGSIZE; 1281 1.1 christos goto bad; 1282 1.1 christos } 1283 1.1 christos 1284 1.1 christos { 1285 1.1 christos int mhlen, firstlen = len; 1286 1.1 christos struct mbuf **mnext = &m->m_act; 1287 1.1 christos 1288 1.1 christos /* 1289 1.1 christos * Loop through length of segment after first fragment, 1290 1.1 christos * make new header and copy data of each part and link onto chain. 1291 1.1 christos */ 1292 1.1 christos m0 = m; 1293 1.1 christos mhlen = sizeof (struct ip); 1294 1.1 christos for (off = hlen + len; off < ip_len; off += len) { 1295 1.1 christos # ifdef MGETHDR 1296 1.1 christos MGETHDR(m, M_DONTWAIT, MT_HEADER); 1297 1.1 christos # else 1298 1.1 christos MGET(m, M_DONTWAIT, MT_HEADER); 1299 1.1 christos # endif 1300 1.1 christos if (m == 0) { 1301 1.1 christos m = m0; 1302 1.1 christos error = ENOBUFS; 1303 1.1 christos goto bad; 1304 1.1 christos } 1305 1.1 christos m->m_data += max_linkhdr; 1306 1.1 christos mhip = mtod(m, struct ip *); 1307 1.1 christos bcopy((char *)ip, (char *)mhip, sizeof(*ip)); 1308 1.2 christos #ifdef INET 1309 1.1 christos if (hlen > sizeof (struct ip)) { 1310 1.1 christos mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); 1311 1.1 christos IP_HL_A(mhip, mhlen >> 2); 1312 1.1 christos } 1313 1.2 christos #endif 1314 1.1 christos m->m_len = mhlen; 1315 1.1 christos mhip->ip_off = ((off - hlen) >> 3) + ip_off; 1316 1.1 christos if (off + len >= ip_len) 1317 1.1 christos len = ip_len - off; 1318 1.1 christos else 1319 1.1 christos mhip->ip_off |= IP_MF; 1320 1.1 christos mhip->ip_len = htons((u_short)(len + mhlen)); 1321 1.27 maxv m->m_next = m_copym(m0, off, len, M_DONTWAIT); 1322 1.1 christos if (m->m_next == 0) { 1323 1.1 christos error = ENOBUFS; /* ??? */ 1324 1.1 christos goto sendorfree; 1325 1.1 christos } 1326 1.1 christos m->m_pkthdr.len = mhlen + len; 1327 1.14 ozaki m_reset_rcvif(m); 1328 1.1 christos mhip->ip_off = htons((u_short)mhip->ip_off); 1329 1.1 christos mhip->ip_sum = 0; 1330 1.2 christos #ifdef INET 1331 1.1 christos mhip->ip_sum = in_cksum(m, mhlen); 1332 1.2 christos #endif 1333 1.1 christos *mnext = m; 1334 1.1 christos mnext = &m->m_act; 1335 1.1 christos } 1336 1.1 christos /* 1337 1.1 christos * Update first fragment by trimming what's been copied out 1338 1.1 christos * and updating header, then send each fragment (in order). 1339 1.1 christos */ 1340 1.1 christos m_adj(m0, hlen + firstlen - ip_len); 1341 1.1 christos ip->ip_len = htons((u_short)(hlen + firstlen)); 1342 1.1 christos ip->ip_off = htons((u_short)IP_MF); 1343 1.1 christos ip->ip_sum = 0; 1344 1.2 christos #ifdef INET 1345 1.1 christos ip->ip_sum = in_cksum(m0, hlen); 1346 1.2 christos #endif 1347 1.1 christos sendorfree: 1348 1.1 christos for (m = m0; m; m = m0) { 1349 1.1 christos m0 = m->m_act; 1350 1.1 christos m->m_act = 0; 1351 1.1 christos if (error == 0) { 1352 1.39 mrg # if __NetBSD_Version__ >= 799003200 1353 1.39 mrg error = if_output_lock(ifp, ifp, m, dst, rt); 1354 1.39 mrg # else 1355 1.9 bouyer KERNEL_LOCK(1, NULL); 1356 1.1 christos error = (*ifp->if_output)(ifp, m, dst, rt); 1357 1.9 bouyer KERNEL_UNLOCK_ONE(NULL); 1358 1.39 mrg # endif 1359 1.1 christos } else { 1360 1.1 christos FREE_MB_T(m); 1361 1.1 christos } 1362 1.1 christos } 1363 1.1 christos } 1364 1.1 christos done: 1365 1.1 christos if (!error) 1366 1.1 christos softc->ipf_frouteok[0]++; 1367 1.1 christos else 1368 1.1 christos softc->ipf_frouteok[1]++; 1369 1.1 christos 1370 1.1 christos # if __NetBSD_Version__ >= 499001100 1371 1.19 ozaki rtcache_unref(rt, ro); 1372 1.1 christos rtcache_free(ro); 1373 1.1 christos # else 1374 1.1 christos if (rt) { 1375 1.1 christos RTFREE(rt); 1376 1.1 christos } 1377 1.1 christos # endif 1378 1.1 christos return error; 1379 1.1 christos bad: 1380 1.1 christos if (error == EMSGSIZE) { 1381 1.1 christos sifp = fin->fin_ifp; 1382 1.1 christos code = fin->fin_icode; 1383 1.1 christos fin->fin_icode = ICMP_UNREACH_NEEDFRAG; 1384 1.1 christos fin->fin_ifp = ifp; 1385 1.1 christos (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1); 1386 1.1 christos fin->fin_ifp = sifp; 1387 1.1 christos fin->fin_icode = code; 1388 1.1 christos } 1389 1.1 christos FREE_MB_T(m); 1390 1.1 christos goto done; 1391 1.1 christos #endif /* INET */ 1392 1.1 christos } 1393 1.1 christos 1394 1.1 christos 1395 1.1 christos #if defined(USE_INET6) 1396 1.1 christos /* 1397 1.1 christos * This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's 1398 1.1 christos * or ensure that it is an IPv6 packet that is being forwarded, those are 1399 1.1 christos * expected to be done by the called (ipf_fastroute). 1400 1.1 christos */ 1401 1.1 christos static int 1402 1.2 christos ipf_fastroute6(struct mbuf *m0, struct mbuf **mpp, fr_info_t *fin, 1403 1.2 christos frdest_t *fdp) 1404 1.1 christos { 1405 1.1 christos # if __NetBSD_Version__ >= 499001100 1406 1.1 christos struct route ip6route; 1407 1.1 christos const struct sockaddr *dst; 1408 1.1 christos union { 1409 1.1 christos struct sockaddr dst; 1410 1.1 christos struct sockaddr_in6 dst6; 1411 1.1 christos } u; 1412 1.1 christos struct route *ro; 1413 1.1 christos # else 1414 1.1 christos struct route_in6 ip6route; 1415 1.1 christos struct sockaddr_in6 *dst6; 1416 1.1 christos struct route_in6 *ro; 1417 1.1 christos # endif 1418 1.1 christos struct rtentry *rt; 1419 1.1 christos struct ifnet *ifp; 1420 1.1 christos u_long mtu; 1421 1.1 christos int error; 1422 1.1 christos 1423 1.1 christos error = 0; 1424 1.1 christos ro = &ip6route; 1425 1.1 christos 1426 1.1 christos if (fdp != NULL) 1427 1.1 christos ifp = fdp->fd_ptr; 1428 1.1 christos else 1429 1.1 christos ifp = fin->fin_ifp; 1430 1.2 christos memset(ro, 0, sizeof(*ro)); 1431 1.1 christos # if __NetBSD_Version__ >= 499001100 1432 1.1 christos if (fdp != NULL && IP6_NOTZERO(&fdp->fd_ip6)) 1433 1.1 christos sockaddr_in6_init(&u.dst6, &fdp->fd_ip6.in6, 0, 0, 0); 1434 1.1 christos else 1435 1.1 christos sockaddr_in6_init(&u.dst6, &fin->fin_fi.fi_dst.in6, 0, 0, 0); 1436 1.26 christos if ((error = in6_setscope(&u.dst6.sin6_addr, ifp, 1437 1.26 christos &u.dst6.sin6_scope_id)) != 0) 1438 1.26 christos return error; 1439 1.26 christos if ((error = sa6_embedscope(&u.dst6, 0)) != 0) 1440 1.26 christos return error; 1441 1.26 christos 1442 1.1 christos dst = &u.dst; 1443 1.1 christos rtcache_setdst(ro, dst); 1444 1.1 christos 1445 1.1 christos rt = rtcache_init(ro); 1446 1.1 christos if ((ifp == NULL) && (rt != NULL)) 1447 1.1 christos ifp = rt->rt_ifp; 1448 1.1 christos # else 1449 1.1 christos dst6 = (struct sockaddr_in6 *)&ro->ro_dst; 1450 1.1 christos dst6->sin6_family = AF_INET6; 1451 1.1 christos dst6->sin6_len = sizeof(struct sockaddr_in6); 1452 1.1 christos dst6->sin6_addr = fin->fin_fi.fi_dst.in6; 1453 1.24 christos /* KAME */ 1454 1.24 christos if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr)) 1455 1.24 christos dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index); 1456 1.1 christos 1457 1.1 christos if (fdp != NULL) { 1458 1.1 christos if (IP6_NOTZERO(&fdp->fd_ip6)) 1459 1.1 christos dst6->sin6_addr = fdp->fd_ip6.in6; 1460 1.1 christos } 1461 1.1 christos 1462 1.1 christos rtalloc((struct route *)ro); 1463 1.1 christos 1464 1.1 christos if ((ifp == NULL) && (ro->ro_rt != NULL)) 1465 1.1 christos ifp = ro->ro_rt->rt_ifp; 1466 1.1 christos rt = ro->ro_rt; 1467 1.1 christos # endif 1468 1.1 christos if ((rt == NULL) || (ifp == NULL)) { 1469 1.1 christos 1470 1.1 christos error = EHOSTUNREACH; 1471 1.1 christos goto bad; 1472 1.1 christos } 1473 1.1 christos 1474 1.1 christos { 1475 1.35 roy # if (__NetBSD_Version__ >= 106010000) && !defined(IN6_LINKMTU) \ 1476 1.35 roy && defined(IPV6CTL_ACCEPT_RTADV) 1477 1.1 christos struct in6_ifextra *ife; 1478 1.1 christos # endif 1479 1.1 christos if (rt->rt_flags & RTF_GATEWAY) 1480 1.1 christos # if __NetBSD_Version__ >= 499001100 1481 1.1 christos dst = rt->rt_gateway; 1482 1.1 christos # else 1483 1.1 christos dst6 = (struct sockaddr_in6 *)rt->rt_gateway; 1484 1.1 christos # endif 1485 1.1 christos rt->rt_use++; 1486 1.1 christos 1487 1.1 christos /* Determine path MTU. */ 1488 1.1 christos # if (__NetBSD_Version__ <= 106009999) 1489 1.1 christos mtu = nd_ifinfo[ifp->if_index].linkmtu; 1490 1.35 roy # elif defined(IPV6CTL_ACCEPT_RTADV) 1491 1.1 christos # ifdef IN6_LINKMTU 1492 1.1 christos mtu = IN6_LINKMTU(ifp); 1493 1.1 christos # else 1494 1.6 martin ife = (struct in6_ifextra *)(ifp)->if_afdata[AF_INET6]; 1495 1.1 christos mtu = ife->nd_ifinfo[ifp->if_index].linkmtu; 1496 1.1 christos # endif 1497 1.35 roy # else 1498 1.35 roy mtu = ifp->if_mtu; 1499 1.1 christos # endif 1500 1.1 christos if ((error == 0) && (m0->m_pkthdr.len <= mtu)) { 1501 1.1 christos # if __NetBSD_Version__ >= 499001100 1502 1.22 ozaki error = ip6_if_output(ifp, ifp, m0, satocsin6(dst), rt); 1503 1.1 christos # else 1504 1.2 christos error = nd6_output(ifp, ifp, m0, dst6, rt); 1505 1.1 christos # endif 1506 1.32 bouyer if (error) 1507 1.33 bouyer *mpp = NULL; /* m0 has been freed */ 1508 1.1 christos } else { 1509 1.1 christos error = EMSGSIZE; 1510 1.1 christos } 1511 1.1 christos } 1512 1.1 christos bad: 1513 1.1 christos # if __NetBSD_Version__ >= 499001100 1514 1.19 ozaki rtcache_unref(rt, ro); 1515 1.1 christos rtcache_free(ro); 1516 1.1 christos # else 1517 1.1 christos if (ro->ro_rt != NULL) { 1518 1.1 christos RTFREE(((struct route *)ro)->ro_rt); 1519 1.1 christos } 1520 1.1 christos # endif 1521 1.1 christos return error; 1522 1.1 christos } 1523 1.1 christos #endif /* INET6 */ 1524 1.1 christos 1525 1.1 christos 1526 1.1 christos int 1527 1.2 christos ipf_verifysrc(fr_info_t *fin) 1528 1.1 christos { 1529 1.1 christos #if __NetBSD_Version__ >= 499001100 1530 1.1 christos union { 1531 1.1 christos struct sockaddr dst; 1532 1.1 christos struct sockaddr_in dst4; 1533 1.1 christos } u; 1534 1.1 christos struct rtentry *rt; 1535 1.1 christos #else 1536 1.1 christos struct sockaddr_in *dst; 1537 1.1 christos #endif 1538 1.1 christos struct route iproute; 1539 1.1 christos int rc; 1540 1.1 christos 1541 1.1 christos #if __NetBSD_Version__ >= 499001100 1542 1.1 christos sockaddr_in_init(&u.dst4, &fin->fin_src, 0); 1543 1.1 christos rtcache_setdst(&iproute, &u.dst); 1544 1.1 christos rt = rtcache_init(&iproute); 1545 1.1 christos if (rt == NULL) 1546 1.1 christos rc = 0; 1547 1.1 christos else 1548 1.1 christos rc = (fin->fin_ifp == rt->rt_ifp); 1549 1.19 ozaki rtcache_unref(rt, &iproute); 1550 1.1 christos rtcache_free(&iproute); 1551 1.1 christos #else 1552 1.1 christos dst = (struct sockaddr_in *)&iproute.ro_dst; 1553 1.1 christos dst->sin_len = sizeof(*dst); 1554 1.1 christos dst->sin_family = AF_INET; 1555 1.1 christos dst->sin_addr = fin->fin_src; 1556 1.1 christos rtalloc(&iproute); 1557 1.1 christos if (iproute.ro_rt == NULL) 1558 1.1 christos return 0; 1559 1.1 christos rc = (fin->fin_ifp == iproute.ro_rt->rt_ifp); 1560 1.1 christos RTFREE(iproute.ro_rt); 1561 1.1 christos #endif 1562 1.1 christos return rc; 1563 1.1 christos } 1564 1.1 christos 1565 1.1 christos 1566 1.1 christos /* 1567 1.1 christos * return the first IP Address associated with an interface 1568 1.1 christos */ 1569 1.1 christos int 1570 1.2 christos ipf_ifpaddr(ipf_main_softc_t *softc, int v, int atype, void *ifptr, 1571 1.2 christos i6addr_t *inp, i6addr_t *inpmask) 1572 1.1 christos { 1573 1.1 christos #ifdef USE_INET6 1574 1.1 christos struct in6_addr *inp6 = NULL; 1575 1.1 christos #endif 1576 1.1 christos struct sockaddr *sock, *mask; 1577 1.1 christos struct sockaddr_in *sin; 1578 1.1 christos struct ifaddr *ifa; 1579 1.1 christos struct ifnet *ifp; 1580 1.1 christos 1581 1.1 christos if ((ifptr == NULL) || (ifptr == (void *)-1)) 1582 1.1 christos return -1; 1583 1.1 christos 1584 1.1 christos ifp = ifptr; 1585 1.1 christos mask = NULL; 1586 1.1 christos 1587 1.1 christos if (v == 4) 1588 1.1 christos inp->in4.s_addr = 0; 1589 1.1 christos #ifdef USE_INET6 1590 1.1 christos else if (v == 6) 1591 1.1 christos bzero((char *)inp, sizeof(*inp)); 1592 1.1 christos #endif 1593 1.1 christos 1594 1.16 ozaki ifa = IFADDR_READER_FIRST(ifp); 1595 1.2 christos sock = ifa ? ifa->ifa_addr : NULL; 1596 1.1 christos while (sock != NULL && ifa != NULL) { 1597 1.1 christos sin = (struct sockaddr_in *)sock; 1598 1.1 christos if ((v == 4) && (sin->sin_family == AF_INET)) 1599 1.1 christos break; 1600 1.1 christos #ifdef USE_INET6 1601 1.1 christos if ((v == 6) && (sin->sin_family == AF_INET6)) { 1602 1.1 christos inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; 1603 1.1 christos if (!IN6_IS_ADDR_LINKLOCAL(inp6) && 1604 1.1 christos !IN6_IS_ADDR_LOOPBACK(inp6)) 1605 1.1 christos break; 1606 1.1 christos } 1607 1.1 christos #endif 1608 1.16 ozaki ifa = IFADDR_READER_NEXT(ifa); 1609 1.1 christos if (ifa != NULL) 1610 1.1 christos sock = ifa->ifa_addr; 1611 1.1 christos } 1612 1.1 christos if (ifa == NULL || sock == NULL) 1613 1.1 christos return -1; 1614 1.1 christos 1615 1.1 christos mask = ifa->ifa_netmask; 1616 1.1 christos if (atype == FRI_BROADCAST) 1617 1.1 christos sock = ifa->ifa_broadaddr; 1618 1.1 christos else if (atype == FRI_PEERADDR) 1619 1.1 christos sock = ifa->ifa_dstaddr; 1620 1.1 christos 1621 1.1 christos #ifdef USE_INET6 1622 1.1 christos if (v == 6) 1623 1.1 christos return ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, 1624 1.1 christos (struct sockaddr_in6 *)mask, 1625 1.1 christos inp, inpmask); 1626 1.1 christos #endif 1627 1.1 christos return ipf_ifpfillv4addr(atype, (struct sockaddr_in *)sock, 1628 1.1 christos (struct sockaddr_in *)mask, 1629 1.1 christos &inp->in4, &inpmask->in4); 1630 1.1 christos } 1631 1.1 christos 1632 1.1 christos 1633 1.1 christos u_32_t 1634 1.2 christos ipf_newisn(fr_info_t *fin) 1635 1.1 christos { 1636 1.1 christos #if __NetBSD_Version__ >= 105190000 /* 1.5T */ 1637 1.1 christos size_t asz; 1638 1.1 christos 1639 1.1 christos if (fin->fin_v == 4) 1640 1.1 christos asz = sizeof(struct in_addr); 1641 1.1 christos else if (fin->fin_v == 6) 1642 1.1 christos asz = sizeof(fin->fin_src); 1643 1.1 christos else /* XXX: no way to return error */ 1644 1.1 christos return 0; 1645 1.2 christos #ifdef INET 1646 1.1 christos return tcp_new_iss1((void *)&fin->fin_src, (void *)&fin->fin_dst, 1647 1.36 christos fin->fin_sport, fin->fin_dport, asz); 1648 1.1 christos #else 1649 1.2 christos return ENOSYS; 1650 1.2 christos #endif 1651 1.2 christos #else 1652 1.1 christos static int iss_seq_off = 0; 1653 1.1 christos u_char hash[16]; 1654 1.1 christos u_32_t newiss; 1655 1.1 christos MD5_CTX ctx; 1656 1.1 christos 1657 1.1 christos /* 1658 1.1 christos * Compute the base value of the ISS. It is a hash 1659 1.1 christos * of (saddr, sport, daddr, dport, secret). 1660 1.1 christos */ 1661 1.1 christos MD5Init(&ctx); 1662 1.1 christos 1663 1.1 christos MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, 1664 1.1 christos sizeof(fin->fin_fi.fi_src)); 1665 1.1 christos MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, 1666 1.1 christos sizeof(fin->fin_fi.fi_dst)); 1667 1.1 christos MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); 1668 1.1 christos 1669 1.1 christos MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); 1670 1.1 christos 1671 1.1 christos MD5Final(hash, &ctx); 1672 1.1 christos 1673 1.1 christos memcpy(&newiss, hash, sizeof(newiss)); 1674 1.1 christos 1675 1.1 christos /* 1676 1.1 christos * Now increment our "timer", and add it in to 1677 1.1 christos * the computed value. 1678 1.1 christos * 1679 1.1 christos * XXX Use `addin'? 1680 1.1 christos * XXX TCP_ISSINCR too large to use? 1681 1.1 christos */ 1682 1.1 christos iss_seq_off += 0x00010000; 1683 1.1 christos newiss += iss_seq_off; 1684 1.1 christos return newiss; 1685 1.1 christos #endif 1686 1.1 christos } 1687 1.1 christos 1688 1.1 christos 1689 1.1 christos /* ------------------------------------------------------------------------ */ 1690 1.38 msaitoh /* Function: ipf_nextipid */ 1691 1.38 msaitoh /* Returns: int - 0 == success, -1 == error (packet should be dropped) */ 1692 1.1 christos /* Parameters: fin(I) - pointer to packet information */ 1693 1.1 christos /* */ 1694 1.1 christos /* Returns the next IPv4 ID to use for this packet. */ 1695 1.1 christos /* ------------------------------------------------------------------------ */ 1696 1.1 christos u_short 1697 1.2 christos ipf_nextipid(fr_info_t *fin) 1698 1.1 christos { 1699 1.1 christos #ifdef USE_MUTEXES 1700 1.1 christos ipf_main_softc_t *softc = fin->fin_main_soft; 1701 1.1 christos #endif 1702 1.1 christos u_short id; 1703 1.1 christos 1704 1.1 christos MUTEX_ENTER(&softc->ipf_rw); 1705 1.1 christos id = ipid++; 1706 1.1 christos MUTEX_EXIT(&softc->ipf_rw); 1707 1.1 christos 1708 1.1 christos return id; 1709 1.1 christos } 1710 1.1 christos 1711 1.1 christos 1712 1.2 christos EXTERN_INLINE int 1713 1.2 christos ipf_checkv4sum(fr_info_t *fin) 1714 1.1 christos { 1715 1.1 christos #ifdef M_CSUM_TCP_UDP_BAD 1716 1.1 christos int manual, pflag, cflags, active; 1717 1.1 christos mb_t *m; 1718 1.1 christos 1719 1.1 christos if ((fin->fin_flx & FI_NOCKSUM) != 0) 1720 1.1 christos return 0; 1721 1.1 christos 1722 1.1 christos if ((fin->fin_flx & FI_SHORT) != 0) 1723 1.1 christos return 1; 1724 1.1 christos 1725 1.3 darrenr if (fin->fin_cksum != FI_CK_NEEDED) 1726 1.3 darrenr return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; 1727 1.1 christos 1728 1.1 christos manual = 0; 1729 1.1 christos m = fin->fin_m; 1730 1.1 christos if (m == NULL) { 1731 1.1 christos manual = 1; 1732 1.1 christos goto skipauto; 1733 1.1 christos } 1734 1.1 christos 1735 1.1 christos switch (fin->fin_p) 1736 1.1 christos { 1737 1.1 christos case IPPROTO_UDP : 1738 1.1 christos pflag = M_CSUM_UDPv4; 1739 1.1 christos break; 1740 1.1 christos case IPPROTO_TCP : 1741 1.1 christos pflag = M_CSUM_TCPv4; 1742 1.1 christos break; 1743 1.1 christos default : 1744 1.1 christos pflag = 0; 1745 1.1 christos manual = 1; 1746 1.1 christos break; 1747 1.1 christos } 1748 1.1 christos 1749 1.1 christos active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag; 1750 1.1 christos active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA; 1751 1.1 christos cflags = m->m_pkthdr.csum_flags & active; 1752 1.1 christos 1753 1.1 christos if (pflag != 0) { 1754 1.1 christos if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) { 1755 1.1 christos fin->fin_flx |= FI_BAD; 1756 1.3 darrenr fin->fin_cksum = FI_CK_BAD; 1757 1.1 christos } else if (cflags == (pflag | M_CSUM_DATA)) { 1758 1.1 christos if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) { 1759 1.1 christos fin->fin_flx |= FI_BAD; 1760 1.3 darrenr fin->fin_cksum = FI_CK_BAD; 1761 1.1 christos } else { 1762 1.3 darrenr fin->fin_cksum = FI_CK_SUMOK; 1763 1.1 christos } 1764 1.1 christos } else if (cflags == pflag) { 1765 1.3 darrenr fin->fin_cksum = FI_CK_SUMOK; 1766 1.1 christos } else { 1767 1.1 christos manual = 1; 1768 1.1 christos } 1769 1.1 christos } 1770 1.1 christos skipauto: 1771 1.1 christos if (manual != 0) { 1772 1.1 christos if (ipf_checkl4sum(fin) == -1) { 1773 1.1 christos fin->fin_flx |= FI_BAD; 1774 1.1 christos return -1; 1775 1.1 christos } 1776 1.1 christos } 1777 1.1 christos #else 1778 1.1 christos if (ipf_checkl4sum(fin) == -1) { 1779 1.1 christos fin->fin_flx |= FI_BAD; 1780 1.1 christos return -1; 1781 1.1 christos } 1782 1.1 christos #endif 1783 1.1 christos return 0; 1784 1.1 christos } 1785 1.1 christos 1786 1.1 christos 1787 1.1 christos #ifdef USE_INET6 1788 1.2 christos EXTERN_INLINE int 1789 1.2 christos ipf_checkv6sum(fr_info_t *fin) 1790 1.1 christos { 1791 1.1 christos # ifdef M_CSUM_TCP_UDP_BAD 1792 1.1 christos int manual, pflag, cflags, active; 1793 1.1 christos mb_t *m; 1794 1.1 christos 1795 1.1 christos if ((fin->fin_flx & FI_NOCKSUM) != 0) 1796 1.1 christos return 0; 1797 1.1 christos 1798 1.1 christos if ((fin->fin_flx & FI_SHORT) != 0) 1799 1.1 christos return 1; 1800 1.1 christos 1801 1.3 darrenr if (fin->fin_cksum != FI_CK_SUMOK) 1802 1.3 darrenr return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; 1803 1.1 christos 1804 1.1 christos 1805 1.1 christos manual = 0; 1806 1.1 christos m = fin->fin_m; 1807 1.1 christos 1808 1.1 christos switch (fin->fin_p) 1809 1.1 christos { 1810 1.1 christos case IPPROTO_UDP : 1811 1.1 christos pflag = M_CSUM_UDPv6; 1812 1.1 christos break; 1813 1.1 christos case IPPROTO_TCP : 1814 1.1 christos pflag = M_CSUM_TCPv6; 1815 1.1 christos break; 1816 1.1 christos default : 1817 1.1 christos pflag = 0; 1818 1.1 christos manual = 1; 1819 1.1 christos break; 1820 1.1 christos } 1821 1.1 christos 1822 1.1 christos active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag; 1823 1.1 christos active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA; 1824 1.1 christos cflags = m->m_pkthdr.csum_flags & active; 1825 1.1 christos 1826 1.1 christos if (pflag != 0) { 1827 1.1 christos if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) { 1828 1.1 christos fin->fin_flx |= FI_BAD; 1829 1.1 christos } else if (cflags == (pflag | M_CSUM_DATA)) { 1830 1.1 christos if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) 1831 1.1 christos fin->fin_flx |= FI_BAD; 1832 1.1 christos } else if (cflags == pflag) { 1833 1.1 christos ; 1834 1.1 christos } else { 1835 1.1 christos manual = 1; 1836 1.1 christos } 1837 1.1 christos } 1838 1.1 christos if (manual != 0) { 1839 1.1 christos if (ipf_checkl4sum(fin) == -1) { 1840 1.1 christos fin->fin_flx |= FI_BAD; 1841 1.1 christos return -1; 1842 1.1 christos } 1843 1.1 christos } 1844 1.1 christos # else 1845 1.1 christos if (ipf_checkl4sum(fin) == -1) { 1846 1.1 christos fin->fin_flx |= FI_BAD; 1847 1.1 christos return -1; 1848 1.1 christos } 1849 1.1 christos # endif 1850 1.1 christos return 0; 1851 1.1 christos } 1852 1.1 christos #endif /* USE_INET6 */ 1853 1.1 christos 1854 1.1 christos 1855 1.1 christos size_t 1856 1.2 christos mbufchainlen(struct mbuf *m0) 1857 1.1 christos { 1858 1.1 christos size_t len; 1859 1.1 christos 1860 1.1 christos if ((m0->m_flags & M_PKTHDR) != 0) { 1861 1.1 christos len = m0->m_pkthdr.len; 1862 1.1 christos } else { 1863 1.1 christos struct mbuf *m; 1864 1.1 christos 1865 1.1 christos for (m = m0, len = 0; m != NULL; m = m->m_next) 1866 1.1 christos len += m->m_len; 1867 1.1 christos } 1868 1.1 christos return len; 1869 1.1 christos } 1870 1.1 christos 1871 1.1 christos 1872 1.1 christos /* ------------------------------------------------------------------------ */ 1873 1.1 christos /* Function: ipf_pullup */ 1874 1.1 christos /* Returns: NULL == pullup failed, else pointer to protocol header */ 1875 1.1 christos /* Parameters: xmin(I)- pointer to buffer where data packet starts */ 1876 1.1 christos /* fin(I) - pointer to packet information */ 1877 1.1 christos /* len(I) - number of bytes to pullup */ 1878 1.1 christos /* */ 1879 1.1 christos /* Attempt to move at least len bytes (from the start of the buffer) into a */ 1880 1.1 christos /* single buffer for ease of access. Operating system native functions are */ 1881 1.1 christos /* used to manage buffers - if necessary. If the entire packet ends up in */ 1882 1.1 christos /* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ 1883 1.1 christos /* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ 1884 1.1 christos /* and ONLY if the pullup succeeds. */ 1885 1.1 christos /* */ 1886 1.1 christos /* We assume that 'xmin' is a pointer to a buffer that is part of the chain */ 1887 1.1 christos /* of buffers that starts at *fin->fin_mp. */ 1888 1.1 christos /* ------------------------------------------------------------------------ */ 1889 1.1 christos void * 1890 1.2 christos ipf_pullup(mb_t *xmin, fr_info_t *fin, int len) 1891 1.1 christos { 1892 1.1 christos int dpoff, ipoff; 1893 1.1 christos mb_t *m = xmin; 1894 1.1 christos char *ip; 1895 1.1 christos 1896 1.1 christos if (m == NULL) 1897 1.1 christos return NULL; 1898 1.1 christos 1899 1.1 christos ip = (char *)fin->fin_ip; 1900 1.1 christos if ((fin->fin_flx & FI_COALESCE) != 0) 1901 1.1 christos return ip; 1902 1.1 christos 1903 1.1 christos ipoff = fin->fin_ipoff; 1904 1.1 christos if (fin->fin_dp != NULL) 1905 1.1 christos dpoff = (char *)fin->fin_dp - (char *)ip; 1906 1.1 christos else 1907 1.1 christos dpoff = 0; 1908 1.1 christos 1909 1.1 christos if (M_LEN(m) < len) { 1910 1.1 christos mb_t *n = *fin->fin_mp; 1911 1.1 christos /* 1912 1.1 christos * Assume that M_PKTHDR is set and just work with what is left 1913 1.1 christos * rather than check.. 1914 1.1 christos * Should not make any real difference, anyway. 1915 1.1 christos */ 1916 1.1 christos if (m != n) { 1917 1.1 christos /* 1918 1.1 christos * Record the mbuf that points to the mbuf that we're 1919 1.1 christos * about to go to work on so that we can update the 1920 1.1 christos * m_next appropriately later. 1921 1.1 christos */ 1922 1.1 christos for (; n->m_next != m; n = n->m_next) 1923 1.1 christos ; 1924 1.1 christos } else { 1925 1.1 christos n = NULL; 1926 1.1 christos } 1927 1.1 christos 1928 1.1 christos #ifdef MHLEN 1929 1.1 christos if (len > MHLEN) 1930 1.1 christos #else 1931 1.1 christos if (len > MLEN) 1932 1.1 christos #endif 1933 1.1 christos { 1934 1.1 christos #ifdef HAVE_M_PULLDOWN 1935 1.1 christos if (m_pulldown(m, 0, len, NULL) == NULL) 1936 1.1 christos m = NULL; 1937 1.1 christos #else 1938 1.1 christos FREE_MB_T(*fin->fin_mp); 1939 1.1 christos m = NULL; 1940 1.1 christos n = NULL; 1941 1.1 christos #endif 1942 1.1 christos } else 1943 1.1 christos { 1944 1.1 christos m = m_pullup(m, len); 1945 1.1 christos } 1946 1.1 christos if (n != NULL) 1947 1.1 christos n->m_next = m; 1948 1.1 christos if (m == NULL) { 1949 1.1 christos /* 1950 1.1 christos * When n is non-NULL, it indicates that m pointed to 1951 1.1 christos * a sub-chain (tail) of the mbuf and that the head 1952 1.1 christos * of this chain has not yet been free'd. 1953 1.1 christos */ 1954 1.1 christos if (n != NULL) { 1955 1.1 christos FREE_MB_T(*fin->fin_mp); 1956 1.1 christos } 1957 1.1 christos 1958 1.1 christos *fin->fin_mp = NULL; 1959 1.1 christos fin->fin_m = NULL; 1960 1.1 christos return NULL; 1961 1.1 christos } 1962 1.1 christos 1963 1.1 christos if (n == NULL) 1964 1.1 christos *fin->fin_mp = m; 1965 1.1 christos 1966 1.1 christos while (M_LEN(m) == 0) { 1967 1.1 christos m = m->m_next; 1968 1.1 christos } 1969 1.1 christos fin->fin_m = m; 1970 1.1 christos ip = MTOD(m, char *) + ipoff; 1971 1.1 christos 1972 1.1 christos fin->fin_ip = (ip_t *)ip; 1973 1.1 christos if (fin->fin_dp != NULL) 1974 1.1 christos fin->fin_dp = (char *)fin->fin_ip + dpoff; 1975 1.3 darrenr if (fin->fin_fraghdr != NULL) 1976 1.3 darrenr fin->fin_fraghdr = (char *)ip + 1977 1.3 darrenr ((char *)fin->fin_fraghdr - 1978 1.3 darrenr (char *)fin->fin_ip); 1979 1.1 christos } 1980 1.1 christos 1981 1.1 christos if (len == fin->fin_plen) 1982 1.1 christos fin->fin_flx |= FI_COALESCE; 1983 1.1 christos return ip; 1984 1.1 christos } 1985 1.1 christos 1986 1.1 christos 1987 1.1 christos int 1988 1.2 christos ipf_inject(fr_info_t *fin, mb_t *m) 1989 1.1 christos { 1990 1.1 christos int error; 1991 1.1 christos 1992 1.1 christos if (fin->fin_out == 0) { 1993 1.10 rmind if (__predict_false(!pktq_enqueue(ip_pktq, m, 0))) { 1994 1.1 christos FREE_MB_T(m); 1995 1.1 christos error = ENOBUFS; 1996 1.1 christos } else { 1997 1.1 christos error = 0; 1998 1.1 christos } 1999 1.1 christos } else { 2000 1.12 riastrad error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); 2001 1.1 christos } 2002 1.1 christos return error; 2003 1.1 christos } 2004 1.1 christos 2005 1.1 christos 2006 1.1 christos u_32_t 2007 1.2 christos ipf_random(void) 2008 1.1 christos { 2009 1.1 christos int number; 2010 1.1 christos 2011 1.1 christos #ifdef _CPRNG_H 2012 1.1 christos number = cprng_fast32(); 2013 1.1 christos #else 2014 1.1 christos number = arc4random(); 2015 1.1 christos #endif 2016 1.1 christos return number; 2017 1.1 christos } 2018 1.1 christos 2019 1.1 christos 2020 1.1 christos /* 2021 1.1 christos * routines below for saving IP headers to buffer 2022 1.1 christos */ 2023 1.2 christos static int ipfopen(dev_t dev, int flags 2024 1.1 christos #if (NetBSD >= 199511) 2025 1.2 christos , int devtype, PROC_T *p 2026 1.2 christos #endif 2027 1.1 christos ) 2028 1.1 christos { 2029 1.1 christos u_int unit = GET_MINOR(dev); 2030 1.1 christos int error; 2031 1.1 christos 2032 1.1 christos if (IPL_LOGMAX < unit) { 2033 1.1 christos error = ENXIO; 2034 1.1 christos } else { 2035 1.1 christos switch (unit) 2036 1.1 christos { 2037 1.1 christos case IPL_LOGIPF : 2038 1.1 christos case IPL_LOGNAT : 2039 1.1 christos case IPL_LOGSTATE : 2040 1.1 christos case IPL_LOGAUTH : 2041 1.1 christos case IPL_LOGLOOKUP : 2042 1.1 christos case IPL_LOGSYNC : 2043 1.1 christos #ifdef IPFILTER_SCAN 2044 1.1 christos case IPL_LOGSCAN : 2045 1.1 christos #endif 2046 1.1 christos error = 0; 2047 1.1 christos break; 2048 1.1 christos default : 2049 1.1 christos error = ENXIO; 2050 1.1 christos break; 2051 1.1 christos } 2052 1.1 christos } 2053 1.13 pgoyette #if (__NetBSD_Version__ >= 799003000) 2054 1.13 pgoyette if (error == 0) { 2055 1.13 pgoyette mutex_enter(&ipf_ref_mutex); 2056 1.13 pgoyette ipf_active = 1; 2057 1.13 pgoyette mutex_exit(&ipf_ref_mutex); 2058 1.13 pgoyette } 2059 1.13 pgoyette #endif 2060 1.1 christos return error; 2061 1.1 christos } 2062 1.1 christos 2063 1.1 christos 2064 1.2 christos static int ipfclose(dev_t dev, int flags 2065 1.1 christos #if (NetBSD >= 199511) 2066 1.2 christos , int devtype, PROC_T *p 2067 1.2 christos #endif 2068 1.1 christos ) 2069 1.1 christos { 2070 1.1 christos u_int unit = GET_MINOR(dev); 2071 1.1 christos 2072 1.1 christos if (IPL_LOGMAX < unit) 2073 1.13 pgoyette return ENXIO; 2074 1.13 pgoyette else { 2075 1.13 pgoyette #if (__NetBSD_Version__ >= 799003000) 2076 1.13 pgoyette mutex_enter(&ipf_ref_mutex); 2077 1.13 pgoyette ipf_active = 0; 2078 1.13 pgoyette mutex_exit(&ipf_ref_mutex); 2079 1.13 pgoyette #endif 2080 1.13 pgoyette return 0; 2081 1.13 pgoyette } 2082 1.1 christos } 2083 1.1 christos 2084 1.1 christos /* 2085 1.1 christos * ipfread/ipflog 2086 1.1 christos * both of these must operate with at least splnet() lest they be 2087 1.1 christos * called during packet processing and cause an inconsistancy to appear in 2088 1.1 christos * the filter lists. 2089 1.1 christos */ 2090 1.2 christos static int ipfread(dev_t dev, struct uio *uio, int ioflag) 2091 1.1 christos { 2092 1.1 christos 2093 1.1 christos if (ipfmain.ipf_running < 1) { 2094 1.1 christos ipfmain.ipf_interror = 130006; 2095 1.1 christos return EIO; 2096 1.1 christos } 2097 1.1 christos 2098 1.1 christos if (GET_MINOR(dev) == IPL_LOGSYNC) 2099 1.1 christos return ipf_sync_read(&ipfmain, uio); 2100 1.1 christos 2101 1.1 christos #ifdef IPFILTER_LOG 2102 1.1 christos return ipf_log_read(&ipfmain, GET_MINOR(dev), uio); 2103 1.1 christos #else 2104 1.1 christos ipfmain.ipf_interror = 130007; 2105 1.1 christos return ENXIO; 2106 1.1 christos #endif 2107 1.1 christos } 2108 1.1 christos 2109 1.1 christos 2110 1.1 christos /* 2111 1.1 christos * ipfwrite 2112 1.1 christos * both of these must operate with at least splnet() lest they be 2113 1.1 christos * called during packet processing and cause an inconsistancy to appear in 2114 1.1 christos * the filter lists. 2115 1.1 christos */ 2116 1.2 christos static int ipfwrite(dev_t dev, struct uio *uio, int ioflag) 2117 1.1 christos { 2118 1.1 christos 2119 1.1 christos if (ipfmain.ipf_running < 1) { 2120 1.1 christos ipfmain.ipf_interror = 130008; 2121 1.1 christos return EIO; 2122 1.1 christos } 2123 1.1 christos 2124 1.1 christos if (GET_MINOR(dev) == IPL_LOGSYNC) 2125 1.1 christos return ipf_sync_write(&ipfmain, uio); 2126 1.1 christos ipfmain.ipf_interror = 130009; 2127 1.1 christos return ENXIO; 2128 1.1 christos } 2129 1.1 christos 2130 1.1 christos 2131 1.2 christos static int ipfpoll(dev_t dev, int events, PROC_T *p) 2132 1.1 christos { 2133 1.1 christos u_int unit = GET_MINOR(dev); 2134 1.1 christos int revents = 0; 2135 1.1 christos 2136 1.1 christos if (IPL_LOGMAX < unit) { 2137 1.1 christos ipfmain.ipf_interror = 130010; 2138 1.1 christos return ENXIO; 2139 1.1 christos } 2140 1.1 christos 2141 1.1 christos switch (unit) 2142 1.1 christos { 2143 1.1 christos case IPL_LOGIPF : 2144 1.1 christos case IPL_LOGNAT : 2145 1.1 christos case IPL_LOGSTATE : 2146 1.1 christos #ifdef IPFILTER_LOG 2147 1.1 christos if ((events & (POLLIN | POLLRDNORM)) && 2148 1.1 christos ipf_log_canread(&ipfmain, unit)) 2149 1.1 christos revents |= events & (POLLIN | POLLRDNORM); 2150 1.1 christos #endif 2151 1.1 christos break; 2152 1.1 christos case IPL_LOGAUTH : 2153 1.1 christos if ((events & (POLLIN | POLLRDNORM)) && 2154 1.1 christos ipf_auth_waiting(&ipfmain)) 2155 1.1 christos revents |= events & (POLLIN | POLLRDNORM); 2156 1.1 christos break; 2157 1.1 christos case IPL_LOGSYNC : 2158 1.1 christos if ((events & (POLLIN | POLLRDNORM)) && 2159 1.1 christos ipf_sync_canread(&ipfmain)) 2160 1.1 christos revents |= events & (POLLIN | POLLRDNORM); 2161 1.1 christos if ((events & (POLLOUT | POLLWRNORM)) && 2162 1.1 christos ipf_sync_canwrite(&ipfmain)) 2163 1.1 christos revents |= events & (POLLOUT | POLLWRNORM); 2164 1.1 christos break; 2165 1.1 christos case IPL_LOGSCAN : 2166 1.1 christos case IPL_LOGLOOKUP : 2167 1.1 christos default : 2168 1.1 christos break; 2169 1.1 christos } 2170 1.1 christos 2171 1.1 christos if ((revents == 0) && (((events & (POLLIN|POLLRDNORM)) != 0))) 2172 1.1 christos selrecord(p, &ipfmain.ipf_selwait[unit]); 2173 1.1 christos return revents; 2174 1.1 christos } 2175 1.1 christos 2176 1.1 christos u_int 2177 1.2 christos ipf_pcksum(fr_info_t *fin, int hlen, u_int sum) 2178 1.1 christos { 2179 1.1 christos struct mbuf *m; 2180 1.1 christos u_int sum2; 2181 1.1 christos int off; 2182 1.1 christos 2183 1.1 christos m = fin->fin_m; 2184 1.1 christos off = (char *)fin->fin_dp - (char *)fin->fin_ip; 2185 1.1 christos m->m_data += hlen; 2186 1.1 christos m->m_len -= hlen; 2187 1.1 christos sum2 = in_cksum(fin->fin_m, fin->fin_plen - off); 2188 1.1 christos m->m_len += hlen; 2189 1.1 christos m->m_data -= hlen; 2190 1.1 christos 2191 1.1 christos /* 2192 1.1 christos * Both sum and sum2 are partial sums, so combine them together. 2193 1.1 christos */ 2194 1.1 christos sum += ~sum2 & 0xffff; 2195 1.1 christos while (sum > 0xffff) 2196 1.1 christos sum = (sum & 0xffff) + (sum >> 16); 2197 1.1 christos sum2 = ~sum & 0xffff; 2198 1.1 christos return sum2; 2199 1.1 christos } 2200 1.13 pgoyette 2201 1.13 pgoyette #if (__NetBSD_Version__ >= 799003000) 2202 1.13 pgoyette 2203 1.13 pgoyette /* NetBSD module interface */ 2204 1.13 pgoyette 2205 1.13 pgoyette MODULE(MODULE_CLASS_DRIVER, ipl, "bpf_filter"); 2206 1.13 pgoyette 2207 1.13 pgoyette static int ipl_init(void *); 2208 1.13 pgoyette static int ipl_fini(void *); 2209 1.13 pgoyette static int ipl_modcmd(modcmd_t, void *); 2210 1.13 pgoyette 2211 1.17 pgoyette #ifdef _MODULE 2212 1.13 pgoyette static devmajor_t ipl_cmaj = -1, ipl_bmaj = -1; 2213 1.17 pgoyette #endif 2214 1.13 pgoyette 2215 1.13 pgoyette static int 2216 1.13 pgoyette ipl_modcmd(modcmd_t cmd, void *opaque) 2217 1.13 pgoyette { 2218 1.13 pgoyette 2219 1.13 pgoyette switch (cmd) { 2220 1.13 pgoyette case MODULE_CMD_INIT: 2221 1.13 pgoyette return ipl_init(opaque); 2222 1.13 pgoyette case MODULE_CMD_FINI: 2223 1.13 pgoyette return ipl_fini(opaque); 2224 1.13 pgoyette default: 2225 1.13 pgoyette return ENOTTY; 2226 1.13 pgoyette } 2227 1.13 pgoyette } 2228 1.13 pgoyette 2229 1.13 pgoyette static int 2230 1.13 pgoyette ipl_init(void *opaque) 2231 1.13 pgoyette { 2232 1.13 pgoyette int error; 2233 1.13 pgoyette 2234 1.13 pgoyette ipf_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK, 2235 1.13 pgoyette ipf_listener_cb, NULL); 2236 1.13 pgoyette 2237 1.13 pgoyette if ((error = ipf_load_all()) != 0) 2238 1.13 pgoyette return error; 2239 1.13 pgoyette 2240 1.13 pgoyette if (ipf_create_all(&ipfmain) == NULL) { 2241 1.13 pgoyette ipf_unload_all(); 2242 1.13 pgoyette return ENODEV; 2243 1.13 pgoyette } 2244 1.13 pgoyette 2245 1.13 pgoyette /* Initialize our mutex and reference count */ 2246 1.13 pgoyette mutex_init(&ipf_ref_mutex, MUTEX_DEFAULT, IPL_NONE); 2247 1.13 pgoyette ipf_active = 0; 2248 1.13 pgoyette 2249 1.17 pgoyette #ifdef _MODULE 2250 1.13 pgoyette /* 2251 1.18 pgoyette * Insert ourself into the cdevsw list. 2252 1.13 pgoyette */ 2253 1.13 pgoyette error = devsw_attach("ipl", NULL, &ipl_bmaj, &ipl_cdevsw, &ipl_cmaj); 2254 1.13 pgoyette if (error) 2255 1.13 pgoyette ipl_fini(opaque); 2256 1.18 pgoyette #endif 2257 1.13 pgoyette 2258 1.13 pgoyette return error; 2259 1.13 pgoyette } 2260 1.13 pgoyette 2261 1.13 pgoyette static int 2262 1.13 pgoyette ipl_fini(void *opaque) 2263 1.13 pgoyette { 2264 1.13 pgoyette 2265 1.17 pgoyette #ifdef _MODULE 2266 1.37 riastrad devsw_detach(NULL, &ipl_cdevsw); 2267 1.17 pgoyette #endif 2268 1.13 pgoyette 2269 1.13 pgoyette /* 2270 1.13 pgoyette * Grab the mutex, verify that there are no references 2271 1.13 pgoyette * and that there are no running filters. If either 2272 1.13 pgoyette * of these exists, reinsert our cdevsw entry and return 2273 1.13 pgoyette * an error. 2274 1.13 pgoyette */ 2275 1.13 pgoyette mutex_enter(&ipf_ref_mutex); 2276 1.13 pgoyette if (ipf_active != 0 || ipfmain.ipf_running > 0) { 2277 1.17 pgoyette #ifdef _MODULE 2278 1.13 pgoyette (void)devsw_attach("ipl", NULL, &ipl_bmaj, 2279 1.13 pgoyette &ipl_cdevsw, &ipl_cmaj); 2280 1.17 pgoyette #endif 2281 1.13 pgoyette mutex_exit(&ipf_ref_mutex); 2282 1.13 pgoyette return EBUSY; 2283 1.13 pgoyette } 2284 1.13 pgoyette 2285 1.13 pgoyette /* Clean up the rest of our state before being unloaded */ 2286 1.13 pgoyette 2287 1.13 pgoyette mutex_exit(&ipf_ref_mutex); 2288 1.13 pgoyette mutex_destroy(&ipf_ref_mutex); 2289 1.13 pgoyette ipf_destroy_all(&ipfmain); 2290 1.13 pgoyette ipf_unload_all(); 2291 1.13 pgoyette kauth_unlisten_scope(ipf_listener); 2292 1.13 pgoyette 2293 1.13 pgoyette return 0; 2294 1.13 pgoyette } 2295 1.13 pgoyette #endif /* (__NetBSD_Version__ >= 799003000) */ 2296