39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/mbuf.h> 43#include <sys/kernel.h> 44#include <sys/socket.h> 45#include <sys/sysctl.h> 46#include <sys/syslog.h> 47#include <net/ethernet.h> /* for ETHERTYPE_IP */ 48#include <net/if.h> 49#include <net/vnet.h> 50#include <net/if_types.h> /* for IFT_ETHER */ 51#include <net/bpf.h> /* for BPF */ 52 53#include <netinet/in.h> 54#include <netinet/ip.h> 55#include <netinet/ip_icmp.h> 56#include <netinet/ip_var.h> 57#include <netinet/ip_fw.h> 58#include <netinet/ipfw/ip_fw_private.h> 59#include <netinet/tcp_var.h> 60#include <netinet/udp.h> 61 62#include <netinet/ip6.h> 63#include <netinet/icmp6.h> 64#ifdef INET6 65#include <netinet6/in6_var.h> /* ip6_sprintf() */ 66#endif 67 68#ifdef MAC 69#include <security/mac/mac_framework.h> 70#endif 71 72/* 73 * L3HDR maps an ipv4 pointer into a layer3 header pointer of type T 74 * Other macros just cast void * into the appropriate type 75 */ 76#define L3HDR(T, ip) ((T *)((u_int32_t *)(ip) + (ip)->ip_hl)) 77#define TCP(p) ((struct tcphdr *)(p)) 78#define SCTP(p) ((struct sctphdr *)(p)) 79#define UDP(p) ((struct udphdr *)(p)) 80#define ICMP(p) ((struct icmphdr *)(p)) 81#define ICMP6(p) ((struct icmp6_hdr *)(p)) 82 83#define SNPARGS(buf, len) buf + len, sizeof(buf) > len ? sizeof(buf) - len : 0 84#define SNP(buf) buf, sizeof(buf) 85 86#ifdef WITHOUT_BPF 87void 88ipfw_log_bpf(int onoff) 89{ 90} 91#else /* !WITHOUT_BPF */ 92static struct ifnet *log_if; /* hook to attach to bpf */ 93 94/* we use this dummy function for all ifnet callbacks */ 95static int 96log_dummy(struct ifnet *ifp, u_long cmd, caddr_t addr) 97{ 98 return EINVAL; 99} 100 101static int 102ipfw_log_output(struct ifnet *ifp, struct mbuf *m, 103 struct sockaddr *dst, struct route *ro) 104{ 105 if (m != NULL) 106 m_freem(m); 107 return EINVAL; 108} 109 110static void 111ipfw_log_start(struct ifnet* ifp) 112{ 113 panic("ipfw_log_start() must not be called"); 114} 115 116static const u_char ipfwbroadcastaddr[6] = 117 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 118 119void 120ipfw_log_bpf(int onoff) 121{ 122 struct ifnet *ifp; 123 124 if (onoff) { 125 if (log_if) 126 return; 127 ifp = if_alloc(IFT_ETHER); 128 if (ifp == NULL) 129 return; 130 if_initname(ifp, "ipfw", 0); 131 ifp->if_mtu = 65536; 132 ifp->if_flags = IFF_UP | IFF_SIMPLEX | IFF_MULTICAST; 133 ifp->if_init = (void *)log_dummy; 134 ifp->if_ioctl = log_dummy; 135 ifp->if_start = ipfw_log_start; 136 ifp->if_output = ipfw_log_output; 137 ifp->if_addrlen = 6; 138 ifp->if_hdrlen = 14; 139 if_attach(ifp); 140 ifp->if_broadcastaddr = ipfwbroadcastaddr; 141 ifp->if_baudrate = IF_Mbps(10); 142 bpfattach(ifp, DLT_EN10MB, 14); 143 log_if = ifp; 144 } else { 145 if (log_if) { 146 ether_ifdetach(log_if); 147 if_free(log_if); 148 } 149 log_if = NULL; 150 } 151} 152#endif /* !WITHOUT_BPF */ 153 154/* 155 * We enter here when we have a rule with O_LOG. 156 * XXX this function alone takes about 2Kbytes of code! 157 */ 158void 159ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args, 160 struct mbuf *m, struct ifnet *oif, u_short offset, uint32_t tablearg, 161 struct ip *ip) 162{ 163 char *action; 164 int limit_reached = 0; 165 char action2[92], proto[128], fragment[32]; 166 167 if (V_fw_verbose == 0) { 168#ifndef WITHOUT_BPF 169 170 if (log_if == NULL || log_if->if_bpf == NULL) 171 return; 172 173 if (args->eh) /* layer2, use orig hdr */ 174 BPF_MTAP2(log_if, args->eh, ETHER_HDR_LEN, m); 175 else 176 /* Add fake header. Later we will store 177 * more info in the header. 178 */ 179 BPF_MTAP2(log_if, "DDDDDDSSSSSS\x08\x00", ETHER_HDR_LEN, m); 180#endif /* !WITHOUT_BPF */ 181 return; 182 } 183 /* the old 'log' function */ 184 fragment[0] = '\0'; 185 proto[0] = '\0'; 186 187 if (f == NULL) { /* bogus pkt */ 188 if (V_verbose_limit != 0 && V_norule_counter >= V_verbose_limit) 189 return; 190 V_norule_counter++; 191 if (V_norule_counter == V_verbose_limit) 192 limit_reached = V_verbose_limit; 193 action = "Refuse"; 194 } else { /* O_LOG is the first action, find the real one */ 195 ipfw_insn *cmd = ACTION_PTR(f); 196 ipfw_insn_log *l = (ipfw_insn_log *)cmd; 197 198 if (l->max_log != 0 && l->log_left == 0) 199 return; 200 l->log_left--; 201 if (l->log_left == 0) 202 limit_reached = l->max_log; 203 cmd += F_LEN(cmd); /* point to first action */ 204 if (cmd->opcode == O_ALTQ) { 205 ipfw_insn_altq *altq = (ipfw_insn_altq *)cmd; 206 207 snprintf(SNPARGS(action2, 0), "Altq %d", 208 altq->qid); 209 cmd += F_LEN(cmd); 210 } 211 if (cmd->opcode == O_PROB) 212 cmd += F_LEN(cmd); 213 214 if (cmd->opcode == O_TAG) 215 cmd += F_LEN(cmd); 216 217 action = action2; 218 switch (cmd->opcode) { 219 case O_DENY: 220 action = "Deny"; 221 break; 222 223 case O_REJECT: 224 if (cmd->arg1==ICMP_REJECT_RST) 225 action = "Reset"; 226 else if (cmd->arg1==ICMP_UNREACH_HOST) 227 action = "Reject"; 228 else 229 snprintf(SNPARGS(action2, 0), "Unreach %d", 230 cmd->arg1); 231 break; 232 233 case O_UNREACH6: 234 if (cmd->arg1==ICMP6_UNREACH_RST) 235 action = "Reset"; 236 else 237 snprintf(SNPARGS(action2, 0), "Unreach %d", 238 cmd->arg1); 239 break; 240 241 case O_ACCEPT: 242 action = "Accept"; 243 break; 244 case O_COUNT: 245 action = "Count"; 246 break; 247 case O_DIVERT: 248 snprintf(SNPARGS(action2, 0), "Divert %d", 249 cmd->arg1); 250 break; 251 case O_TEE: 252 snprintf(SNPARGS(action2, 0), "Tee %d", 253 cmd->arg1); 254 break; 255 case O_SETFIB: 256 snprintf(SNPARGS(action2, 0), "SetFib %d", 257 cmd->arg1); 258 break; 259 case O_SKIPTO: 260 snprintf(SNPARGS(action2, 0), "SkipTo %d", 261 cmd->arg1); 262 break; 263 case O_PIPE: 264 snprintf(SNPARGS(action2, 0), "Pipe %d", 265 cmd->arg1); 266 break; 267 case O_QUEUE: 268 snprintf(SNPARGS(action2, 0), "Queue %d", 269 cmd->arg1); 270 break; 271 case O_FORWARD_IP: { 272 ipfw_insn_sa *sa = (ipfw_insn_sa *)cmd; 273 int len; 274 struct in_addr dummyaddr; 275 if (sa->sa.sin_addr.s_addr == INADDR_ANY) 276 dummyaddr.s_addr = htonl(tablearg); 277 else 278 dummyaddr.s_addr = sa->sa.sin_addr.s_addr; 279 280 len = snprintf(SNPARGS(action2, 0), "Forward to %s", 281 inet_ntoa(dummyaddr)); 282 283 if (sa->sa.sin_port) 284 snprintf(SNPARGS(action2, len), ":%d", 285 sa->sa.sin_port); 286 } 287 break; 288#ifdef INET6 289 case O_FORWARD_IP6: { 290 char buf[INET6_ADDRSTRLEN]; 291 ipfw_insn_sa6 *sa = (ipfw_insn_sa6 *)cmd; 292 int len; 293 294 len = snprintf(SNPARGS(action2, 0), "Forward to [%s]", 295 ip6_sprintf(buf, &sa->sa.sin6_addr)); 296 297 if (sa->sa.sin6_port) 298 snprintf(SNPARGS(action2, len), ":%u", 299 sa->sa.sin6_port); 300 } 301 break; 302#endif 303 case O_NETGRAPH: 304 snprintf(SNPARGS(action2, 0), "Netgraph %d", 305 cmd->arg1); 306 break; 307 case O_NGTEE: 308 snprintf(SNPARGS(action2, 0), "Ngtee %d", 309 cmd->arg1); 310 break; 311 case O_NAT: 312 action = "Nat"; 313 break; 314 case O_REASS: 315 action = "Reass"; 316 break; 317 case O_CALLRETURN: 318 if (cmd->len & F_NOT) 319 action = "Return"; 320 else 321 snprintf(SNPARGS(action2, 0), "Call %d", 322 cmd->arg1); 323 break; 324 default: 325 action = "UNKNOWN"; 326 break; 327 } 328 } 329 330 if (hlen == 0) { /* non-ip */ 331 snprintf(SNPARGS(proto, 0), "MAC"); 332 333 } else { 334 int len; 335#ifdef INET6 336 char src[INET6_ADDRSTRLEN + 2], dst[INET6_ADDRSTRLEN + 2]; 337#else 338 char src[INET_ADDRSTRLEN], dst[INET_ADDRSTRLEN]; 339#endif 340 struct icmphdr *icmp; 341 struct tcphdr *tcp; 342 struct udphdr *udp; 343#ifdef INET6 344 struct ip6_hdr *ip6 = NULL; 345 struct icmp6_hdr *icmp6; 346 u_short ip6f_mf; 347#endif 348 src[0] = '\0'; 349 dst[0] = '\0'; 350#ifdef INET6 351 ip6f_mf = offset & IP6F_MORE_FRAG; 352 offset &= IP6F_OFF_MASK; 353 354 if (IS_IP6_FLOW_ID(&(args->f_id))) { 355 char ip6buf[INET6_ADDRSTRLEN]; 356 snprintf(src, sizeof(src), "[%s]", 357 ip6_sprintf(ip6buf, &args->f_id.src_ip6)); 358 snprintf(dst, sizeof(dst), "[%s]", 359 ip6_sprintf(ip6buf, &args->f_id.dst_ip6)); 360 361 ip6 = (struct ip6_hdr *)ip; 362 tcp = (struct tcphdr *)(((char *)ip) + hlen); 363 udp = (struct udphdr *)(((char *)ip) + hlen); 364 } else 365#endif 366 { 367 tcp = L3HDR(struct tcphdr, ip); 368 udp = L3HDR(struct udphdr, ip); 369 370 inet_ntoa_r(ip->ip_src, src); 371 inet_ntoa_r(ip->ip_dst, dst); 372 } 373 374 switch (args->f_id.proto) { 375 case IPPROTO_TCP: 376 len = snprintf(SNPARGS(proto, 0), "TCP %s", src); 377 if (offset == 0) 378 snprintf(SNPARGS(proto, len), ":%d %s:%d", 379 ntohs(tcp->th_sport), 380 dst, 381 ntohs(tcp->th_dport)); 382 else 383 snprintf(SNPARGS(proto, len), " %s", dst); 384 break; 385 386 case IPPROTO_UDP: 387 len = snprintf(SNPARGS(proto, 0), "UDP %s", src); 388 if (offset == 0) 389 snprintf(SNPARGS(proto, len), ":%d %s:%d", 390 ntohs(udp->uh_sport), 391 dst, 392 ntohs(udp->uh_dport)); 393 else 394 snprintf(SNPARGS(proto, len), " %s", dst); 395 break; 396 397 case IPPROTO_ICMP: 398 icmp = L3HDR(struct icmphdr, ip); 399 if (offset == 0) 400 len = snprintf(SNPARGS(proto, 0), 401 "ICMP:%u.%u ", 402 icmp->icmp_type, icmp->icmp_code); 403 else 404 len = snprintf(SNPARGS(proto, 0), "ICMP "); 405 len += snprintf(SNPARGS(proto, len), "%s", src); 406 snprintf(SNPARGS(proto, len), " %s", dst); 407 break; 408#ifdef INET6 409 case IPPROTO_ICMPV6: 410 icmp6 = (struct icmp6_hdr *)(((char *)ip) + hlen); 411 if (offset == 0) 412 len = snprintf(SNPARGS(proto, 0), 413 "ICMPv6:%u.%u ", 414 icmp6->icmp6_type, icmp6->icmp6_code); 415 else 416 len = snprintf(SNPARGS(proto, 0), "ICMPv6 "); 417 len += snprintf(SNPARGS(proto, len), "%s", src); 418 snprintf(SNPARGS(proto, len), " %s", dst); 419 break; 420#endif 421 default: 422 len = snprintf(SNPARGS(proto, 0), "P:%d %s", 423 args->f_id.proto, src); 424 snprintf(SNPARGS(proto, len), " %s", dst); 425 break; 426 } 427 428#ifdef INET6 429 if (IS_IP6_FLOW_ID(&(args->f_id))) { 430 if (offset & (IP6F_OFF_MASK | IP6F_MORE_FRAG)) 431 snprintf(SNPARGS(fragment, 0), 432 " (frag %08x:%d@%d%s)", 433 args->f_id.extra, 434 ntohs(ip6->ip6_plen) - hlen, 435 ntohs(offset) << 3, ip6f_mf ? "+" : ""); 436 } else 437#endif 438 { 439 int ipoff, iplen; 440 ipoff = ntohs(ip->ip_off); 441 iplen = ntohs(ip->ip_len); 442 if (ipoff & (IP_MF | IP_OFFMASK)) 443 snprintf(SNPARGS(fragment, 0), 444 " (frag %d:%d@%d%s)", 445 ntohs(ip->ip_id), iplen - (ip->ip_hl << 2), 446 offset << 3, 447 (ipoff & IP_MF) ? "+" : ""); 448 } 449 } 450#ifdef __FreeBSD__ 451 if (oif || m->m_pkthdr.rcvif) 452 log(LOG_SECURITY | LOG_INFO, 453 "ipfw: %d %s %s %s via %s%s\n", 454 f ? f->rulenum : -1, 455 action, proto, oif ? "out" : "in", 456 oif ? oif->if_xname : m->m_pkthdr.rcvif->if_xname, 457 fragment); 458 else 459#endif 460 log(LOG_SECURITY | LOG_INFO, 461 "ipfw: %d %s %s [no if info]%s\n", 462 f ? f->rulenum : -1, 463 action, proto, fragment); 464 if (limit_reached) 465 log(LOG_SECURITY | LOG_NOTICE, 466 "ipfw: limit %d reached on entry %d\n", 467 limit_reached, f ? f->rulenum : -1); 468} 469/* end of file */
|