1 /* $OpenBSD: if_pflow.c,v 1.11 2009/06/17 06:35:30 gollo Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Henning Brauer <henning@openbsd.org> 5 * Copyright (c) 2008 Joerg Goltermann <jg@osn.de> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN 16 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/types.h> 21 #include <sys/malloc.h> 22 #include <sys/param.h> 23 #include <sys/mbuf.h> 24 #include <sys/socket.h> 25 #include <sys/ioctl.h> 26 #include <sys/kernel.h> 27 #include <sys/sysctl.h> 28 #include <dev/rndvar.h> 29 30 #include <net/if.h> 31 #include <net/if_types.h> 32 #include <net/bpf.h> 33 #include <net/route.h> 34 #include <netinet/in.h> 35 #include <netinet/if_ether.h> 36 #include <netinet/tcp.h> 37 38 #ifdef INET 39 #include <netinet/in.h> 40 #include <netinet/in_var.h> 41 #include <netinet/in_systm.h> 42 #include <netinet/ip.h> 43 #include <netinet/ip_var.h> 44 #include <netinet/udp.h> 45 #include <netinet/udp_var.h> 46 #include <netinet/in_pcb.h> 47 #endif /* INET */ 48 49 #include <net/pfvar.h> 50 #include <net/if_pflow.h> 51 52 #include "bpfilter.h" 53 #include "pflow.h" 54 55 #define PFLOW_MINMTU \ 56 (sizeof(struct pflow_header) + sizeof(struct pflow_flow)) 57 58 #ifdef PFLOWDEBUG 59 #define DPRINTF(x) do { printf x ; } while (0) 60 #else 61 #define DPRINTF(x) 62 #endif 63 64 SLIST_HEAD(, pflow_softc) pflowif_list; 65 struct pflowstats pflowstats; 66 67 void pflowattach(int); 68 int pflow_clone_create(struct if_clone *, int); 69 int pflow_clone_destroy(struct ifnet *); 70 void pflow_setmtu(struct pflow_softc *, int); 71 int pflowoutput(struct ifnet *, struct mbuf *, struct sockaddr *, 72 struct rtentry *); 73 int pflowioctl(struct ifnet *, u_long, caddr_t); 74 void pflowstart(struct ifnet *); 75 76 struct mbuf *pflow_get_mbuf(struct pflow_softc *); 77 int pflow_sendout(struct pflow_softc *); 78 int pflow_sendout_mbuf(struct pflow_softc *, struct mbuf *); 79 void pflow_timeout(void *); 80 void copy_flow_data(struct pflow_flow *, struct pflow_flow *, 81 struct pf_state *, int, int); 82 int pflow_pack_flow(struct pf_state *, struct pflow_softc *); 83 int pflow_get_dynport(void); 84 int export_pflow_if(struct pf_state*, struct pflow_softc *); 85 int copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc); 86 87 struct if_clone pflow_cloner = 88 IF_CLONE_INITIALIZER("pflow", pflow_clone_create, 89 pflow_clone_destroy); 90 91 /* from in_pcb.c */ 92 extern int ipport_hifirstauto; 93 extern int ipport_hilastauto; 94 95 /* from kern/kern_clock.c; incremented each clock tick. */ 96 extern int ticks; 97 98 void 99 pflowattach(int npflow) 100 { 101 SLIST_INIT(&pflowif_list); 102 if_clone_attach(&pflow_cloner); 103 } 104 105 int 106 pflow_clone_create(struct if_clone *ifc, int unit) 107 { 108 struct ifnet *ifp; 109 struct pflow_softc *pflowif; 110 111 if ((pflowif = malloc(sizeof(*pflowif), 112 M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) 113 return (ENOMEM); 114 115 pflowif->sc_sender_ip.s_addr = INADDR_ANY; 116 pflowif->sc_sender_port = pflow_get_dynport(); 117 118 pflowif->sc_imo.imo_membership = malloc( 119 (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_IPMOPTS, 120 M_WAITOK|M_ZERO); 121 pflowif->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS; 122 pflowif->sc_receiver_ip.s_addr = 0; 123 pflowif->sc_receiver_port = 0; 124 pflowif->sc_sender_ip.s_addr = INADDR_ANY; 125 pflowif->sc_sender_port = pflow_get_dynport(); 126 ifp = &pflowif->sc_if; 127 snprintf(ifp->if_xname, sizeof ifp->if_xname, "pflow%d", unit); 128 ifp->if_softc = pflowif; 129 ifp->if_ioctl = pflowioctl; 130 ifp->if_output = pflowoutput; 131 ifp->if_start = pflowstart; 132 ifp->if_type = IFT_PFLOW; 133 ifp->if_snd.ifq_maxlen = ifqmaxlen; 134 ifp->if_hdrlen = PFLOW_HDRLEN; 135 ifp->if_flags = IFF_UP; 136 ifp->if_flags &= ~IFF_RUNNING; /* not running, need receiver */ 137 pflow_setmtu(pflowif, ETHERMTU); 138 timeout_set(&pflowif->sc_tmo, pflow_timeout, pflowif); 139 if_attach(ifp); 140 if_alloc_sadl(ifp); 141 142 #if NBPFILTER > 0 143 bpfattach(&pflowif->sc_if.if_bpf, ifp, DLT_RAW, 0); 144 #endif 145 146 /* Insert into list of pflows */ 147 SLIST_INSERT_HEAD(&pflowif_list, pflowif, sc_next); 148 return (0); 149 } 150 151 int 152 pflow_clone_destroy(struct ifnet *ifp) 153 { 154 struct pflow_softc *sc = ifp->if_softc; 155 int s; 156 157 s = splnet(); 158 pflow_sendout(sc); 159 #if NBPFILTER > 0 160 bpfdetach(ifp); 161 #endif 162 if_detach(ifp); 163 SLIST_REMOVE(&pflowif_list, sc, pflow_softc, sc_next); 164 free(sc->sc_imo.imo_membership, M_IPMOPTS); 165 free(sc, M_DEVBUF); 166 splx(s); 167 return (0); 168 } 169 170 /* 171 * Start output on the pflow interface. 172 */ 173 void 174 pflowstart(struct ifnet *ifp) 175 { 176 struct mbuf *m; 177 int s; 178 179 for (;;) { 180 s = splnet(); 181 IF_DROP(&ifp->if_snd); 182 IF_DEQUEUE(&ifp->if_snd, m); 183 splx(s); 184 185 if (m == NULL) 186 return; 187 m_freem(m); 188 } 189 } 190 191 int 192 pflowoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 193 struct rtentry *rt) 194 { 195 m_freem(m); 196 return (0); 197 } 198 199 /* ARGSUSED */ 200 int 201 pflowioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 202 { 203 struct proc *p = curproc; 204 struct pflow_softc *sc = ifp->if_softc; 205 struct ifreq *ifr = (struct ifreq *)data; 206 struct pflowreq pflowr; 207 int s, error; 208 209 switch (cmd) { 210 case SIOCSIFADDR: 211 case SIOCAIFADDR: 212 case SIOCSIFDSTADDR: 213 case SIOCSIFFLAGS: 214 if ((ifp->if_flags & IFF_UP) && 215 sc->sc_receiver_ip.s_addr != 0 && 216 sc->sc_receiver_port != 0) { 217 ifp->if_flags |= IFF_RUNNING; 218 sc->sc_gcounter=pflowstats.pflow_flows; 219 } else 220 ifp->if_flags &= ~IFF_RUNNING; 221 break; 222 case SIOCSIFMTU: 223 if (ifr->ifr_mtu < PFLOW_MINMTU) 224 return (EINVAL); 225 if (ifr->ifr_mtu > MCLBYTES) 226 ifr->ifr_mtu = MCLBYTES; 227 s = splnet(); 228 if (ifr->ifr_mtu < ifp->if_mtu) 229 pflow_sendout(sc); 230 pflow_setmtu(sc, ifr->ifr_mtu); 231 splx(s); 232 break; 233 234 case SIOCGETPFLOW: 235 bzero(&pflowr, sizeof(pflowr)); 236 237 pflowr.sender_ip = sc->sc_sender_ip; 238 pflowr.receiver_ip = sc->sc_receiver_ip; 239 pflowr.receiver_port = sc->sc_receiver_port; 240 241 if ((error = copyout(&pflowr, ifr->ifr_data, 242 sizeof(pflowr)))) 243 return (error); 244 break; 245 246 case SIOCSETPFLOW: 247 if ((error = suser(p, p->p_acflag)) != 0) 248 return (error); 249 if ((error = copyin(ifr->ifr_data, &pflowr, 250 sizeof(pflowr)))) 251 return (error); 252 253 s = splnet(); 254 pflow_sendout(sc); 255 splx(s); 256 257 if (pflowr.addrmask & PFLOW_MASK_DSTIP) 258 sc->sc_receiver_ip = pflowr.receiver_ip; 259 if (pflowr.addrmask & PFLOW_MASK_DSTPRT) 260 sc->sc_receiver_port = pflowr.receiver_port; 261 if (pflowr.addrmask & PFLOW_MASK_SRCIP) 262 sc->sc_sender_ip.s_addr = pflowr.sender_ip.s_addr; 263 264 if ((ifp->if_flags & IFF_UP) && 265 sc->sc_receiver_ip.s_addr != 0 && 266 sc->sc_receiver_port != 0) { 267 ifp->if_flags |= IFF_RUNNING; 268 sc->sc_gcounter=pflowstats.pflow_flows; 269 } else 270 ifp->if_flags &= ~IFF_RUNNING; 271 272 break; 273 274 default: 275 return (ENOTTY); 276 } 277 return (0); 278 } 279 280 void 281 pflow_setmtu(struct pflow_softc *sc, int mtu_req) 282 { 283 int mtu; 284 285 if (sc->sc_pflow_ifp && sc->sc_pflow_ifp->if_mtu < mtu_req) 286 mtu = sc->sc_pflow_ifp->if_mtu; 287 else 288 mtu = mtu_req; 289 290 sc->sc_maxcount = (mtu - sizeof(struct pflow_header) - 291 sizeof (struct udpiphdr)) / sizeof(struct pflow_flow); 292 if (sc->sc_maxcount > PFLOW_MAXFLOWS) 293 sc->sc_maxcount = PFLOW_MAXFLOWS; 294 sc->sc_if.if_mtu = sizeof(struct pflow_header) + 295 sizeof (struct udpiphdr) + 296 sc->sc_maxcount * sizeof(struct pflow_flow); 297 } 298 299 struct mbuf * 300 pflow_get_mbuf(struct pflow_softc *sc) 301 { 302 struct pflow_header h; 303 struct mbuf *m; 304 305 MGETHDR(m, M_DONTWAIT, MT_DATA); 306 if (m == NULL) { 307 pflowstats.pflow_onomem++; 308 return (NULL); 309 } 310 311 MCLGET(m, M_DONTWAIT); 312 if ((m->m_flags & M_EXT) == 0) { 313 m_free(m); 314 pflowstats.pflow_onomem++; 315 return (NULL); 316 } 317 318 m->m_len = m->m_pkthdr.len = 0; 319 m->m_pkthdr.rcvif = NULL; 320 321 /* populate pflow_header */ 322 h.reserved1 = 0; 323 h.reserved2 = 0; 324 h.count = 0; 325 h.version = htons(PFLOW_VERSION); 326 h.flow_sequence = htonl(sc->sc_gcounter); 327 h.engine_type = PFLOW_ENGINE_TYPE; 328 h.engine_id = PFLOW_ENGINE_ID; 329 m_copyback(m, 0, PFLOW_HDRLEN, &h); 330 331 sc->sc_count = 0; 332 timeout_add_sec(&sc->sc_tmo, PFLOW_TIMEOUT); 333 return (m); 334 } 335 336 void 337 copy_flow_data(struct pflow_flow *flow1, struct pflow_flow *flow2, 338 struct pf_state *st, int src, int dst) 339 { 340 struct pf_state_key *sk = st->key[PF_SK_WIRE]; 341 342 flow1->src_ip = flow2->dest_ip = sk->addr[src].v4.s_addr; 343 flow1->src_port = flow2->dest_port = sk->port[src]; 344 flow1->dest_ip = flow2->src_ip = sk->addr[dst].v4.s_addr; 345 flow1->dest_port = flow2->src_port = sk->port[dst]; 346 347 flow1->dest_as = flow2->src_as = 348 flow1->src_as = flow2->dest_as = 0; 349 flow1->if_index_out = flow2->if_index_in = 350 flow1->if_index_in = flow2->if_index_out = 0; 351 flow1->dest_mask = flow2->src_mask = 352 flow1->src_mask = flow2->dest_mask = 0; 353 354 flow1->flow_packets = htonl(st->packets[0]); 355 flow2->flow_packets = htonl(st->packets[1]); 356 flow1->flow_octets = htonl(st->bytes[0]); 357 flow2->flow_octets = htonl(st->bytes[1]); 358 359 flow1->flow_start = flow2->flow_start = 360 htonl((st->creation - (time_second - time_uptime)) * 1000); 361 flow1->flow_finish = flow2->flow_finish = 362 htonl((time_uptime - (st->rule.ptr->timeout[st->timeout] ? 363 st->rule.ptr->timeout[st->timeout] : 364 pf_default_rule.timeout[st->timeout])) * 1000); 365 flow1->tcp_flags = flow2->tcp_flags = 0; 366 flow1->protocol = flow2->protocol = sk->proto; 367 flow1->tos = flow2->tos = st->rule.ptr->tos; 368 } 369 370 int 371 export_pflow(struct pf_state *st) 372 { 373 struct pflow_softc *sc = NULL; 374 struct pf_state_key *sk = st->key[PF_SK_WIRE]; 375 376 if (sk->af != AF_INET) 377 return (0); 378 379 SLIST_FOREACH(sc, &pflowif_list, sc_next) { 380 export_pflow_if(st, sc); 381 } 382 383 return (0); 384 } 385 386 int 387 export_pflow_if(struct pf_state *st, struct pflow_softc *sc) 388 { 389 struct pf_state pfs_copy; 390 struct ifnet *ifp = &sc->sc_if; 391 u_int64_t bytes[2]; 392 int ret = 0; 393 394 if (!(ifp->if_flags & IFF_RUNNING)) 395 return (0); 396 397 if ((st->bytes[0] < (u_int64_t)PFLOW_MAXBYTES) 398 && (st->bytes[1] < (u_int64_t)PFLOW_MAXBYTES)) 399 return (pflow_pack_flow(st, sc)); 400 401 /* flow > PFLOW_MAXBYTES need special handling */ 402 bcopy(st, &pfs_copy, sizeof(pfs_copy)); 403 bytes[0] = pfs_copy.bytes[0]; 404 bytes[1] = pfs_copy.bytes[1]; 405 406 while (bytes[0] > PFLOW_MAXBYTES) { 407 pfs_copy.bytes[0] = PFLOW_MAXBYTES; 408 pfs_copy.bytes[1] = 0; 409 410 if ((ret = pflow_pack_flow(&pfs_copy, sc)) != 0) 411 return (ret); 412 if ((bytes[0] - PFLOW_MAXBYTES) > 0) 413 bytes[0] -= PFLOW_MAXBYTES; 414 } 415 416 while (bytes[1] > (u_int64_t)PFLOW_MAXBYTES) { 417 pfs_copy.bytes[1] = PFLOW_MAXBYTES; 418 pfs_copy.bytes[0] = 0; 419 420 if ((ret = pflow_pack_flow(&pfs_copy, sc)) != 0) 421 return (ret); 422 if ((bytes[1] - PFLOW_MAXBYTES) > 0) 423 bytes[1] -= PFLOW_MAXBYTES; 424 } 425 426 pfs_copy.bytes[0] = bytes[0]; 427 pfs_copy.bytes[1] = bytes[1]; 428 429 return (pflow_pack_flow(&pfs_copy, sc)); 430 } 431 432 int 433 copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc) 434 { 435 int s, ret = 0; 436 437 s = splnet(); 438 if (sc->sc_mbuf == NULL) { 439 if ((sc->sc_mbuf = pflow_get_mbuf(sc)) == NULL) { 440 splx(s); 441 return (ENOBUFS); 442 } 443 } 444 m_copyback(sc->sc_mbuf, PFLOW_HDRLEN + 445 (sc->sc_count * sizeof (struct pflow_flow)), 446 sizeof (struct pflow_flow), flow); 447 448 if (pflowstats.pflow_flows == sc->sc_gcounter) 449 pflowstats.pflow_flows++; 450 sc->sc_gcounter++; 451 sc->sc_count++; 452 453 if (sc->sc_count >= sc->sc_maxcount) 454 ret = pflow_sendout(sc); 455 456 splx(s); 457 return(ret); 458 } 459 460 int 461 pflow_pack_flow(struct pf_state *st, struct pflow_softc *sc) 462 { 463 struct pflow_flow flow1; 464 struct pflow_flow flow2; 465 int ret = 0; 466 467 bzero(&flow1, sizeof(flow1)); 468 bzero(&flow2, sizeof(flow2)); 469 470 if (st->direction == PF_OUT) 471 copy_flow_data(&flow1, &flow2, st, 1, 0); 472 else 473 copy_flow_data(&flow1, &flow2, st, 0, 1); 474 475 if (st->bytes[0] != 0) /* first flow from state */ 476 ret = copy_flow_to_m(&flow1, sc); 477 478 if (st->bytes[1] != 0) /* second flow from state */ 479 ret = copy_flow_to_m(&flow2, sc); 480 481 return (ret); 482 } 483 484 void 485 pflow_timeout(void *v) 486 { 487 struct pflow_softc *sc = v; 488 int s; 489 490 s = splnet(); 491 pflow_sendout(sc); 492 splx(s); 493 } 494 495 /* This must be called in splnet() */ 496 int 497 pflow_sendout(struct pflow_softc *sc) 498 { 499 struct mbuf *m = sc->sc_mbuf; 500 struct pflow_header *h; 501 struct ifnet *ifp = &sc->sc_if; 502 503 timeout_del(&sc->sc_tmo); 504 505 if (m == NULL) 506 return (0); 507 508 sc->sc_mbuf = NULL; 509 if (!(ifp->if_flags & IFF_RUNNING)) { 510 m_freem(m); 511 return (0); 512 } 513 514 pflowstats.pflow_packets++; 515 h = mtod(m, struct pflow_header *); 516 h->count = htons(sc->sc_count); 517 518 /* populate pflow_header */ 519 h->uptime_ms = htonl(time_uptime * 1000); 520 h->time_sec = htonl(time_second); 521 h->time_nanosec = htonl(ticks); 522 523 return (pflow_sendout_mbuf(sc, m)); 524 } 525 526 int 527 pflow_sendout_mbuf(struct pflow_softc *sc, struct mbuf *m) 528 { 529 struct udpiphdr *ui; 530 u_int16_t len = m->m_pkthdr.len; 531 struct ifnet *ifp = &sc->sc_if; 532 struct ip *ip; 533 int err; 534 535 /* UDP Header*/ 536 M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT); 537 if (m == NULL) { 538 pflowstats.pflow_onomem++; 539 return (ENOBUFS); 540 } 541 542 ui = mtod(m, struct udpiphdr *); 543 ui->ui_pr = IPPROTO_UDP; 544 ui->ui_src = sc->sc_sender_ip; 545 ui->ui_sport = sc->sc_sender_port; 546 ui->ui_dst = sc->sc_receiver_ip; 547 ui->ui_dport = sc->sc_receiver_port; 548 ui->ui_ulen = htons(sizeof (struct udphdr) + len); 549 550 ip = (struct ip *)ui; 551 ip->ip_v = IPVERSION; 552 ip->ip_hl = sizeof(struct ip) >> 2; 553 ip->ip_id = htons(ip_randomid()); 554 ip->ip_off = htons(IP_DF); 555 ip->ip_tos = IPTOS_LOWDELAY; 556 ip->ip_ttl = IPDEFTTL; 557 ip->ip_len = htons(sizeof (struct udpiphdr) + len); 558 559 /* 560 * Compute the pseudo-header checksum; defer further checksumming 561 * until ip_output() or hardware (if it exists). 562 */ 563 m->m_pkthdr.csum_flags |= M_UDPV4_CSUM_OUT; 564 ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr, 565 ui->ui_dst.s_addr, htons(len + sizeof(struct udphdr) + 566 IPPROTO_UDP)); 567 568 #if NBPFILTER > 0 569 if (ifp->if_bpf) { 570 ip->ip_sum = in_cksum(m, ip->ip_hl << 2); 571 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); 572 } 573 #endif 574 575 sc->sc_if.if_opackets++; 576 sc->sc_if.if_obytes += m->m_pkthdr.len; 577 578 if ((err = ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL))) { 579 pflowstats.pflow_oerrors++; 580 sc->sc_if.if_oerrors++; 581 } 582 return (err); 583 } 584 585 int 586 pflow_get_dynport(void) 587 { 588 u_int16_t tmp, low, high, cut; 589 590 low = ipport_hifirstauto; /* sysctl */ 591 high = ipport_hilastauto; 592 593 cut = arc4random_uniform(1 + high - low) + low; 594 595 for (tmp = cut; tmp <= high; ++(tmp)) { 596 if (!in_baddynamic(tmp, IPPROTO_UDP)) 597 return (htons(tmp)); 598 } 599 600 for (tmp = cut - 1; tmp >= low; --(tmp)) { 601 if (!in_baddynamic(tmp, IPPROTO_UDP)) 602 return (htons(tmp)); 603 } 604 605 return (htons(ipport_hilastauto)); /* XXX */ 606 } 607 608 int 609 pflow_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 610 void *newp, size_t newlen) 611 { 612 if (namelen != 1) 613 return (ENOTDIR); 614 615 switch (name[0]) { 616 case NET_PFLOW_STATS: 617 if (newp != NULL) 618 return (EPERM); 619 return (sysctl_struct(oldp, oldlenp, newp, newlen, 620 &pflowstats, sizeof(pflowstats))); 621 default: 622 return (EOPNOTSUPP); 623 } 624 return (0); 625 } 626