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