1 /* $OpenBSD: if_pflow.c,v 1.5 2008/09/17 22:18:00 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 struct pflow_softc *pflowif = NULL; 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 *, void **); 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 *); 83 int pflow_get_dynport(void); 84 85 struct if_clone pflow_cloner = 86 IF_CLONE_INITIALIZER("pflow", pflow_clone_create, 87 pflow_clone_destroy); 88 89 /* from in_pcb.c */ 90 extern int ipport_hifirstauto; 91 extern int ipport_hilastauto; 92 93 void 94 pflowattach(int npflow) 95 { 96 if_clone_attach(&pflow_cloner); 97 } 98 99 int 100 pflow_clone_create(struct if_clone *ifc, int unit) 101 { 102 struct ifnet *ifp; 103 104 if (unit != 0) 105 return (EINVAL); 106 107 if ((pflowif = malloc(sizeof(*pflowif), 108 M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) 109 return (ENOMEM); 110 111 pflowif->sc_sender_ip.s_addr = INADDR_ANY; 112 pflowif->sc_sender_port = pflow_get_dynport(); 113 114 pflowif->sc_imo.imo_membership = malloc( 115 (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_IPMOPTS, 116 M_WAITOK|M_ZERO); 117 pflowif->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS; 118 pflowif->sc_receiver_ip.s_addr = 0; 119 pflowif->sc_receiver_port = 0; 120 pflowif->sc_sender_ip.s_addr = INADDR_ANY; 121 pflowif->sc_sender_port = pflow_get_dynport(); 122 ifp = &pflowif->sc_if; 123 snprintf(ifp->if_xname, sizeof ifp->if_xname, "pflow%d", unit); 124 ifp->if_softc = pflowif; 125 ifp->if_ioctl = pflowioctl; 126 ifp->if_output = pflowoutput; 127 ifp->if_start = pflowstart; 128 ifp->if_type = IFT_PFLOW; 129 ifp->if_snd.ifq_maxlen = ifqmaxlen; 130 ifp->if_hdrlen = PFLOW_HDRLEN; 131 ifp->if_flags = IFF_UP; 132 ifp->if_flags &= ~IFF_RUNNING; /* not running, need receiver */ 133 pflow_setmtu(pflowif, ETHERMTU); 134 timeout_set(&pflowif->sc_tmo, pflow_timeout, pflowif); 135 if_attach(ifp); 136 if_alloc_sadl(ifp); 137 138 return (0); 139 } 140 141 int 142 pflow_clone_destroy(struct ifnet *ifp) 143 { 144 struct pflow_softc *sc = ifp->if_softc; 145 146 timeout_del(&sc->sc_tmo); 147 148 #if NBPFILTER > 0 149 bpfdetach(ifp); 150 #endif 151 if_detach(ifp); 152 free(pflowif->sc_imo.imo_membership, M_IPMOPTS); 153 free(pflowif, M_DEVBUF); 154 pflowif = NULL; 155 return (0); 156 } 157 158 /* 159 * Start output on the pflow interface. 160 */ 161 void 162 pflowstart(struct ifnet *ifp) 163 { 164 struct mbuf *m; 165 int s; 166 167 for (;;) { 168 s = splnet(); 169 IF_DROP(&ifp->if_snd); 170 IF_DEQUEUE(&ifp->if_snd, m); 171 splx(s); 172 173 if (m == NULL) 174 return; 175 m_freem(m); 176 } 177 } 178 179 int 180 pflowoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 181 struct rtentry *rt) 182 { 183 m_freem(m); 184 return (0); 185 } 186 187 /* ARGSUSED */ 188 int 189 pflowioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 190 { 191 struct proc *p = curproc; 192 struct pflow_softc *sc = ifp->if_softc; 193 struct ifreq *ifr = (struct ifreq *)data; 194 struct pflowreq pflowr; 195 int s, error; 196 197 switch (cmd) { 198 case SIOCSIFADDR: 199 case SIOCAIFADDR: 200 case SIOCSIFDSTADDR: 201 case SIOCSIFFLAGS: 202 if ((ifp->if_flags & IFF_UP) && 203 sc->sc_receiver_ip.s_addr != 0 && 204 sc->sc_receiver_port != 0) 205 ifp->if_flags |= IFF_RUNNING; 206 else 207 ifp->if_flags &= ~IFF_RUNNING; 208 break; 209 case SIOCSIFMTU: 210 if (ifr->ifr_mtu < PFLOW_MINMTU) 211 return (EINVAL); 212 if (ifr->ifr_mtu > MCLBYTES) 213 ifr->ifr_mtu = MCLBYTES; 214 s = splnet(); 215 if (ifr->ifr_mtu < ifp->if_mtu) 216 pflow_sendout(sc); 217 pflow_setmtu(sc, ifr->ifr_mtu); 218 splx(s); 219 break; 220 221 case SIOCGETPFLOW: 222 bzero(&pflowr, sizeof(pflowr)); 223 224 pflowr.sender_ip = sc->sc_sender_ip; 225 pflowr.receiver_ip = sc->sc_receiver_ip; 226 pflowr.receiver_port = sc->sc_receiver_port; 227 228 if ((error = copyout(&pflowr, ifr->ifr_data, 229 sizeof(pflowr)))) 230 return (error); 231 break; 232 233 case SIOCSETPFLOW: 234 if ((error = suser(p, p->p_acflag)) != 0) 235 return (error); 236 if ((error = copyin(ifr->ifr_data, &pflowr, 237 sizeof(pflowr)))) 238 return (error); 239 240 if ((ifp->if_flags & IFF_UP) && sc->sc_receiver_ip.s_addr != 0 241 && sc->sc_receiver_port != 0) { 242 s = splnet(); 243 pflow_sendout(sc); 244 splx(s); 245 } 246 247 if (pflowr.addrmask & PFLOW_MASK_DSTIP) 248 sc->sc_receiver_ip = pflowr.receiver_ip; 249 if (pflowr.addrmask & PFLOW_MASK_DSTPRT) 250 sc->sc_receiver_port = pflowr.receiver_port; 251 if (pflowr.addrmask & PFLOW_MASK_SRCIP) 252 sc->sc_sender_ip.s_addr = pflowr.sender_ip.s_addr; 253 254 if ((ifp->if_flags & IFF_UP) && 255 sc->sc_receiver_ip.s_addr != 0 && 256 sc->sc_receiver_port != 0) 257 ifp->if_flags |= IFF_RUNNING; 258 else 259 ifp->if_flags &= ~IFF_RUNNING; 260 261 break; 262 263 default: 264 return (ENOTTY); 265 } 266 return (0); 267 } 268 269 void 270 pflow_setmtu(struct pflow_softc *sc, int mtu_req) 271 { 272 int mtu; 273 274 if (sc->sc_pflow_ifp && sc->sc_pflow_ifp->if_mtu < mtu_req) 275 mtu = sc->sc_pflow_ifp->if_mtu; 276 else 277 mtu = mtu_req; 278 279 sc->sc_maxcount = (mtu - sizeof(struct pflow_header)) / 280 sizeof(struct pflow_flow); 281 if (sc->sc_maxcount > PFLOW_MAXFLOWS) 282 sc->sc_maxcount = PFLOW_MAXFLOWS; 283 sc->sc_if.if_mtu = sizeof(struct pflow_header) + 284 sc->sc_maxcount * sizeof(struct pflow_flow); 285 } 286 287 struct mbuf * 288 pflow_get_mbuf(struct pflow_softc *sc, void **sp) 289 { 290 struct pflow_header *h; 291 struct mbuf *m, *top = NULL, **mp = ⊤ 292 int len, totlen; 293 294 MGETHDR(m, M_DONTWAIT, MT_DATA); 295 if (m == NULL) { 296 sc->sc_if.if_oerrors++; 297 return (NULL); 298 } 299 300 len = MHLEN; 301 totlen = (sc->sc_maxcount * sizeof(struct pflow_flow)) + 302 sizeof(struct pflow_header); 303 304 while (totlen > 0) { 305 if (top) { 306 MGET(m, M_DONTWAIT, MT_DATA); 307 if (m == 0) { 308 m_freem(top); 309 sc->sc_if.if_oerrors++; 310 return (NULL); 311 } 312 len = MLEN; 313 } 314 if (totlen >= MINCLSIZE) { 315 MCLGET(m, M_DONTWAIT); 316 if (m->m_flags & M_EXT) 317 len = MCLBYTES; 318 else { 319 m_free(m); 320 m_freem(top); 321 sc->sc_if.if_oerrors++; 322 return (NULL); 323 } 324 } 325 m->m_len = len = min(totlen, len); 326 totlen -= len; 327 *mp = m; 328 mp = &m->m_next; 329 } 330 331 top->m_pkthdr.rcvif = NULL; 332 top->m_len = m->m_pkthdr.len = sizeof(struct pflow_header); 333 334 /* populate pflow_header */ 335 h = mtod(top, struct pflow_header *); 336 h->reserved1 = 0; 337 h->reserved2 = 0; 338 h->count = 0; 339 h->version = htons(PFLOW_VERSION); 340 h->flow_sequence = htonl(sc->sc_gcounter); 341 h->engine_type = PFLOW_ENGINE_TYPE; 342 h->engine_id = PFLOW_ENGINE_ID; 343 344 sc->sc_count = 0; 345 *sp = (void *)((char *)h + PFLOW_HDRLEN); 346 timeout_add_sec(&sc->sc_tmo, PFLOW_TIMEOUT); 347 return (top); 348 } 349 350 void 351 copy_flow_data(struct pflow_flow *flow1, struct pflow_flow *flow2, 352 struct pf_state *st, int src, int dst) 353 { 354 struct pf_state_key *sk = st->key[PF_SK_WIRE]; 355 356 flow1->src_ip = flow2->dest_ip = 357 st->key[PF_SK_WIRE]->addr[src].v4.s_addr; 358 flow1->src_port = flow2->dest_port = st->key[PF_SK_WIRE]->port[src]; 359 flow1->dest_ip = flow2->src_ip = 360 st->key[PF_SK_WIRE]->addr[dst].v4.s_addr; 361 flow1->dest_port = flow2->src_port = st->key[PF_SK_WIRE]->port[dst]; 362 363 flow1->dest_as = flow2->src_as = 364 flow1->src_as = flow2->dest_as = 0; 365 flow1->if_index_out = flow2->if_index_in = 366 flow1->if_index_in = flow2->if_index_out = 0; 367 flow1->dest_mask = flow2->src_mask = 368 flow1->src_mask = flow2->dest_mask = 0; 369 370 flow1->flow_packets = htonl(st->packets[0]); 371 flow2->flow_packets = htonl(st->packets[1]); 372 flow1->flow_octets = htonl(st->bytes[0]); 373 flow2->flow_octets = htonl(st->bytes[1]); 374 375 flow1->flow_start = flow2->flow_start = htonl(st->creation * 1000); 376 flow1->flow_finish = flow2->flow_finish = htonl(time_second * 1000); 377 flow1->tcp_flags = flow2->tcp_flags = 0; 378 flow1->protocol = flow2->protocol = sk->proto; 379 flow1->tos = flow2->tos = st->rule.ptr->tos; 380 } 381 382 int 383 export_pflow(struct pf_state *st) 384 { 385 struct pf_state pfs_copy; 386 struct pflow_softc *sc = pflowif; 387 struct ifnet *ifp = NULL; 388 u_int64_t bytes[2]; 389 int ret = 0; 390 391 if (sc == NULL) 392 return (0); 393 394 ifp = &sc->sc_if; 395 if (!(ifp->if_flags & IFF_UP)) 396 return (0); 397 398 if ((st->bytes[0] < (u_int64_t)PFLOW_MAXBYTES) 399 && (st->bytes[1] < (u_int64_t)PFLOW_MAXBYTES)) 400 return pflow_pack_flow(st); 401 402 /* flow > PFLOW_MAXBYTES need special handling */ 403 bcopy(st, &pfs_copy, sizeof(pfs_copy)); 404 bytes[0] = pfs_copy.bytes[0]; 405 bytes[1] = pfs_copy.bytes[1]; 406 407 while (bytes[0] > PFLOW_MAXBYTES) { 408 pfs_copy.bytes[0] = PFLOW_MAXBYTES; 409 pfs_copy.bytes[1] = 0; 410 411 if ((ret = pflow_pack_flow(&pfs_copy)) != 0) 412 return (ret); 413 if ((bytes[0] - PFLOW_MAXBYTES) > 0) 414 bytes[0] -= PFLOW_MAXBYTES; 415 } 416 417 while (bytes[1] > (u_int64_t)PFLOW_MAXBYTES) { 418 pfs_copy.bytes[1] = PFLOW_MAXBYTES; 419 pfs_copy.bytes[0] = 0; 420 421 if ((ret = pflow_pack_flow(&pfs_copy)) != 0) 422 return (ret); 423 if ((bytes[1] - PFLOW_MAXBYTES) > 0) 424 bytes[1] -= PFLOW_MAXBYTES; 425 } 426 427 pfs_copy.bytes[0] = bytes[0]; 428 pfs_copy.bytes[1] = bytes[1]; 429 430 return (pflow_pack_flow(&pfs_copy)); 431 } 432 433 int 434 pflow_pack_flow(struct pf_state *st) 435 { 436 struct pflow_softc *sc = pflowif; 437 struct pflow_flow *flow1 = NULL; 438 struct pflow_flow flow2; 439 struct pf_state_key *sk = st->key[PF_SK_WIRE]; 440 int s, ret = 0; 441 442 if (sk->af != AF_INET) 443 return (0); 444 445 s = splnet(); 446 447 if (sc->sc_mbuf == NULL) { 448 if ((sc->sc_mbuf = pflow_get_mbuf(sc, 449 (void **)&sc->sc_flowp.s)) == NULL) { 450 splx(s); 451 return (ENOMEM); 452 } 453 } 454 455 pflowstats.pflow_flows++; 456 sc->sc_gcounter++; 457 sc->sc_count++; 458 459 flow1 = sc->sc_flowp.s++; 460 sc->sc_mbuf->m_pkthdr.len = 461 sc->sc_mbuf->m_len += sizeof(struct pflow_flow); 462 bzero(flow1, sizeof(*flow1)); 463 bzero(&flow2, sizeof(flow2)); 464 465 if (st->direction == PF_OUT) 466 copy_flow_data(flow1, &flow2, st, 1, 0); 467 else 468 copy_flow_data(flow1, &flow2, st, 0, 1); 469 470 if (st->bytes[0] != 0) { /* first flow from state */ 471 if (sc->sc_count >= sc->sc_maxcount) 472 ret = pflow_sendout(sc); 473 474 if (st->bytes[1] != 0) { 475 /* one more flow, second part from state */ 476 if (sc->sc_mbuf == NULL) { 477 if ((sc->sc_mbuf = pflow_get_mbuf(sc, 478 (void **)&sc->sc_flowp.s)) == NULL) { 479 splx(s); 480 return (ENOMEM); 481 } 482 } 483 484 pflowstats.pflow_flows++; 485 sc->sc_gcounter++; 486 sc->sc_count++; 487 488 flow1 = sc->sc_flowp.s++; 489 sc->sc_mbuf->m_pkthdr.len = 490 sc->sc_mbuf->m_len += sizeof(struct pflow_flow); 491 bzero(flow1, sizeof(*flow1)); 492 } 493 } 494 495 if (st->bytes[1] != 0) { /* second flow from state */ 496 bcopy(&flow2, flow1, sizeof(*flow1)); 497 if (sc->sc_count >= sc->sc_maxcount) 498 ret = pflow_sendout(sc); 499 } 500 501 splx(s); 502 return (ret); 503 } 504 505 void 506 pflow_timeout(void *v) 507 { 508 struct pflow_softc *sc = v; 509 int s; 510 511 s = splnet(); 512 pflow_sendout(sc); 513 splx(s); 514 } 515 516 /* This must be called in splnet() */ 517 int 518 pflow_sendout(struct pflow_softc *sc) 519 { 520 struct mbuf *m = sc->sc_mbuf; 521 struct pflow_header *h; 522 #if NBPFILTER > 0 523 struct ifnet *ifp = &sc->sc_if; 524 #endif 525 526 timeout_del(&sc->sc_tmo); 527 528 if (m == NULL) 529 return (0); 530 531 sc->sc_mbuf = NULL; 532 sc->sc_flowp.s = NULL; 533 if (!(ifp->if_flags & IFF_RUNNING)) { 534 m_freem(m); 535 return (0); 536 } 537 538 pflowstats.pflow_packets++; 539 h = mtod(m, struct pflow_header *); 540 h->count = htons(sc->sc_count); 541 542 /* populate pflow_header */ 543 h->uptime_ms = htonl(time_uptime * 1000); 544 h->time_sec = htonl(time_second); 545 h->time_nanosec = htonl(ticks); 546 547 #if NBPFILTER > 0 548 if (ifp->if_bpf) 549 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); 550 #endif 551 552 return (pflow_sendout_mbuf(sc, m)); 553 } 554 555 int 556 pflow_sendout_mbuf(struct pflow_softc *sc, struct mbuf *m) 557 { 558 struct udpiphdr *ui; 559 int len = m->m_pkthdr.len; 560 561 /* UDP Header*/ 562 M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT); 563 if (m == NULL) { 564 pflowstats.pflow_onomem++; 565 return (0); 566 } 567 568 ui = mtod(m, struct udpiphdr *); 569 ui->ui_pr = IPPROTO_UDP; 570 ui->ui_len = htons((u_int16_t) len + sizeof (struct udphdr)); 571 ui->ui_src = sc->sc_sender_ip; 572 ui->ui_sport = sc->sc_sender_port; 573 ui->ui_dst = sc->sc_receiver_ip; 574 ui->ui_dport = sc->sc_receiver_port; 575 ui->ui_ulen = ui->ui_len; 576 577 ((struct ip *)ui)->ip_v = IPVERSION; 578 ((struct ip *)ui)->ip_hl = sizeof(struct ip) >> 2; 579 ((struct ip *)ui)->ip_id = htons(ip_randomid()); 580 ((struct ip *)ui)->ip_off = htons(IP_DF); 581 ((struct ip *)ui)->ip_tos = IPTOS_LOWDELAY; 582 ((struct ip *)ui)->ip_ttl = IPDEFTTL; 583 ((struct ip *)ui)->ip_len = htons(sizeof (struct udpiphdr) + len); 584 585 /* 586 * Compute the pseudo-header checksum; defer further checksumming 587 * until ip_output() or hardware (if it exists). 588 */ 589 m->m_pkthdr.csum_flags |= M_UDPV4_CSUM_OUT; 590 ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr, 591 ui->ui_dst.s_addr, htons((u_int16_t)len + 592 sizeof(struct udphdr) + IPPROTO_UDP)); 593 594 if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL)) 595 pflowstats.pflow_oerrors++; 596 return (0); 597 } 598 599 int 600 pflow_get_dynport(void) 601 { 602 u_int16_t tmp, low, high, cut; 603 604 low = ipport_hifirstauto; /* sysctl */ 605 high = ipport_hilastauto; 606 607 cut = arc4random_uniform(1 + high - low) + low; 608 609 for (tmp = cut; tmp <= high; ++(tmp)) { 610 if (!in_baddynamic(tmp, IPPROTO_UDP)) 611 return (htons(tmp)); 612 } 613 614 for (tmp = cut - 1; tmp >= low; --(tmp)) { 615 if (!in_baddynamic(tmp, IPPROTO_UDP)) 616 return (htons(tmp)); 617 } 618 619 return (htons(ipport_hilastauto)); /* XXX */ 620 } 621 622 int 623 pflow_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 624 void *newp, size_t newlen) 625 { 626 if (namelen != 1) 627 return (ENOTDIR); 628 629 switch (name[0]) { 630 case NET_PFLOW_STATS: 631 if (newp != NULL) 632 return (EPERM); 633 return (sysctl_struct(oldp, oldlenp, newp, newlen, 634 &pflowstats, sizeof(pflowstats))); 635 default: 636 return (EOPNOTSUPP); 637 } 638 return (0); 639 } 640