1 /* $OpenBSD: print-pfsync.c,v 1.42 2016/10/27 13:55:21 millert Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Michael Shalayeff 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/time.h> 30 #include <sys/socket.h> 31 #include <sys/file.h> 32 #include <sys/ioctl.h> 33 34 #ifdef __STDC__ 35 struct rtentry; 36 #endif 37 #include <net/if.h> 38 39 #include <netinet/in.h> 40 #include <netinet/ip.h> 41 42 #include <net/pfvar.h> 43 #include <net/if_pfsync.h> 44 45 #include <ctype.h> 46 #include <netdb.h> 47 #include <pcap.h> 48 #include <signal.h> 49 #include <stdio.h> 50 #include <string.h> 51 #include <vis.h> 52 53 #include "interface.h" 54 #include "addrtoname.h" 55 #include "pfctl_parser.h" 56 #include "pfctl.h" 57 58 void pfsync_print(struct pfsync_header *, const u_char *, int); 59 60 void 61 pfsync_if_print(u_char *user, const struct pcap_pkthdr *h, 62 const u_char *p) 63 { 64 u_int caplen = h->caplen; 65 66 ts_print(&h->ts); 67 68 if (caplen < PFSYNC_HDRLEN) { 69 printf("[|pfsync]"); 70 goto out; 71 } 72 73 pfsync_print((struct pfsync_header *)p, 74 p + sizeof(struct pfsync_header), 75 caplen - sizeof(struct pfsync_header)); 76 out: 77 if (xflag) { 78 default_print((const u_char *)p, caplen); 79 } 80 putchar('\n'); 81 } 82 83 void 84 pfsync_ip_print(const u_char *bp, u_int len, const u_char *bp2) 85 { 86 struct pfsync_header *hdr = (struct pfsync_header *)bp; 87 struct ip *ip = (struct ip *)bp2; 88 89 if (vflag) 90 printf("%s > %s: ", ipaddr_string(&ip->ip_src), 91 ipaddr_string(&ip->ip_dst)); 92 else 93 printf("%s: ", ipaddr_string(&ip->ip_src)); 94 95 if (len < PFSYNC_HDRLEN) 96 printf("[|pfsync]"); 97 else 98 pfsync_print(hdr, bp + sizeof(struct pfsync_header), 99 len - sizeof(struct pfsync_header)); 100 putchar('\n'); 101 } 102 103 const char *actnames[] = { PFSYNC_ACTIONS }; 104 105 struct pfsync_actions { 106 size_t len; 107 int (*print)(int, const void *); 108 }; 109 110 int pfsync_print_clr(int, const void *); 111 int pfsync_print_state(int, const void *); 112 int pfsync_print_ins_ack(int, const void *); 113 int pfsync_print_upd_c(int, const void *); 114 int pfsync_print_upd_req(int, const void *); 115 int pfsync_print_del_c(int, const void *); 116 int pfsync_print_bus(int, const void *); 117 int pfsync_print_tdb(int, const void *); 118 int pfsync_print_eof(int, const void *); 119 120 struct pfsync_actions actions[] = { 121 { sizeof(struct pfsync_clr), pfsync_print_clr }, 122 { 0, NULL }, 123 { sizeof(struct pfsync_ins_ack), pfsync_print_ins_ack }, 124 { 0, NULL }, 125 { sizeof(struct pfsync_upd_c), pfsync_print_upd_c }, 126 { sizeof(struct pfsync_upd_req), pfsync_print_upd_req }, 127 { sizeof(struct pfsync_state), pfsync_print_state }, 128 { sizeof(struct pfsync_del_c), pfsync_print_del_c }, 129 { 0, NULL }, 130 { 0, NULL }, 131 { sizeof(struct pfsync_bus), pfsync_print_bus }, 132 { 0, NULL }, 133 { 0, pfsync_print_eof }, 134 { sizeof(struct pfsync_state), pfsync_print_state }, 135 { sizeof(struct pfsync_state), pfsync_print_state }, 136 { sizeof(struct pfsync_tdb), pfsync_print_tdb }, 137 }; 138 139 void 140 pfsync_print(struct pfsync_header *hdr, const u_char *bp, int len) 141 { 142 struct pfsync_subheader *subh; 143 int count, plen, alen, flags = 0; 144 int i; 145 146 plen = ntohs(hdr->len); 147 148 printf("PFSYNCv%d len %d", hdr->version, plen); 149 150 if (hdr->version != PFSYNC_VERSION) 151 return; 152 153 plen -= sizeof(*hdr); 154 155 if (vflag) 156 flags |= PF_OPT_VERBOSE; 157 if (vflag > 1) 158 flags |= PF_OPT_VERBOSE2; 159 if (!nflag) 160 flags |= PF_OPT_USEDNS; 161 162 while (plen > 0) { 163 if (len < sizeof(*subh)) 164 break; 165 166 subh = (struct pfsync_subheader *)bp; 167 bp += sizeof(*subh); 168 len -= sizeof(*subh); 169 plen -= sizeof(*subh); 170 171 if (subh->action >= PFSYNC_ACT_MAX) { 172 printf("\n act UNKNOWN id %d", subh->action); 173 return; 174 } 175 176 count = ntohs(subh->count); 177 printf("\n act %s count %d", actnames[subh->action], count); 178 alen = actions[subh->action].len; 179 180 if (actions[subh->action].print == NULL) { 181 printf("\n unimplemented action"); 182 return; 183 } 184 185 for (i = 0; i < count; i++) { 186 if (len < alen) { 187 len = 0; 188 break; 189 } 190 191 if (actions[subh->action].print(flags, bp) != 0) 192 return; 193 194 bp += alen; 195 len -= alen; 196 plen -= alen; 197 } 198 } 199 200 if (plen > 0) { 201 printf("\n ..."); 202 return; 203 } 204 if (plen < 0) { 205 printf("\n invalid header length"); 206 return; 207 } 208 if (len > 0) 209 printf("\n invalid packet length"); 210 } 211 212 int 213 pfsync_print_clr(int flags, const void *bp) 214 { 215 const struct pfsync_clr *clr = bp; 216 char ifname[IFNAMSIZ * 4 + 1]; 217 char *cp = ifname; 218 int i; 219 220 printf("\n\tcreatorid: %08x", htonl(clr->creatorid)); 221 if (clr->ifname[0] != '\0') { 222 /* Treat clr->ifname as untrusted input. */ 223 for (i = 0; i < IFNAMSIZ && clr->ifname[i] != '\0'; i++) 224 cp = vis(cp, clr->ifname[i], VIS_WHITE, 0); 225 printf(" interface: %s", ifname); 226 } 227 228 return (0); 229 } 230 231 int 232 pfsync_print_state(int flags, const void *bp) 233 { 234 struct pfsync_state *st = (struct pfsync_state *)bp; 235 putchar('\n'); 236 print_state(st, flags); 237 return (0); 238 } 239 240 int 241 pfsync_print_ins_ack(int flags, const void *bp) 242 { 243 const struct pfsync_ins_ack *iack = bp; 244 245 printf("\n\tid: %016llx creatorid: %08x", betoh64(iack->id), 246 ntohl(iack->creatorid)); 247 248 return (0); 249 } 250 251 int 252 pfsync_print_upd_c(int flags, const void *bp) 253 { 254 const struct pfsync_upd_c *u = bp; 255 256 printf("\n\tid: %016llx creatorid: %08x", betoh64(u->id), 257 ntohl(u->creatorid)); 258 259 return (0); 260 } 261 262 int 263 pfsync_print_upd_req(int flags, const void *bp) 264 { 265 const struct pfsync_upd_req *ur = bp; 266 267 printf("\n\tid: %016llx creatorid: %08x", betoh64(ur->id), 268 ntohl(ur->creatorid)); 269 270 return (0); 271 } 272 273 int 274 pfsync_print_del_c(int flags, const void *bp) 275 { 276 const struct pfsync_del_c *d = bp; 277 278 printf("\n\tid: %016llx creatorid: %08x", betoh64(d->id), 279 ntohl(d->creatorid)); 280 281 return (0); 282 } 283 284 int 285 pfsync_print_bus(int flags, const void *bp) 286 { 287 const struct pfsync_bus *b = bp; 288 u_int32_t endtime; 289 int min, sec; 290 const char *status; 291 292 endtime = ntohl(b->endtime); 293 sec = endtime % 60; 294 endtime /= 60; 295 min = endtime % 60; 296 endtime /= 60; 297 298 switch (b->status) { 299 case PFSYNC_BUS_START: 300 status = "start"; 301 break; 302 case PFSYNC_BUS_END: 303 status = "end"; 304 break; 305 default: 306 status = "UNKNOWN"; 307 break; 308 } 309 310 printf("\n\tcreatorid: %08x age: %.2u:%.2u:%.2u status: %s", 311 htonl(b->creatorid), endtime, min, sec, status); 312 313 return (0); 314 } 315 316 int 317 pfsync_print_tdb(int flags, const void *bp) 318 { 319 const struct pfsync_tdb *t = bp; 320 321 printf("\n\tspi: 0x%08x rpl: %llu cur_bytes: %llu", 322 ntohl(t->spi), betoh64(t->rpl), betoh64(t->cur_bytes)); 323 324 return (0); 325 } 326 327 int 328 pfsync_print_eof(int flags, const void *bp) 329 { 330 return (1); 331 } 332