1 /* $OpenBSD: print-pfsync.c,v 1.44 2021/12/01 18:28:46 deraadt 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 #include <net/if.h> 35 36 #include <netinet/in.h> 37 #include <netinet/ip.h> 38 #include <netinet/ip_ipsp.h> 39 40 #include <net/pfvar.h> 41 #include <net/if_pfsync.h> 42 43 #include <ctype.h> 44 #include <netdb.h> 45 #include <pcap.h> 46 #include <signal.h> 47 #include <stdio.h> 48 #include <string.h> 49 #include <vis.h> 50 51 #include "interface.h" 52 #include "addrtoname.h" 53 #include "pfctl_parser.h" 54 #include "pfctl.h" 55 56 void pfsync_print(struct pfsync_header *, const u_char *, int); 57 58 void 59 pfsync_if_print(u_char *user, const struct pcap_pkthdr *h, 60 const u_char *p) 61 { 62 u_int caplen = h->caplen; 63 64 ts_print(&h->ts); 65 66 if (caplen < PFSYNC_HDRLEN) { 67 printf("[|pfsync]"); 68 goto out; 69 } 70 71 pfsync_print((struct pfsync_header *)p, 72 p + sizeof(struct pfsync_header), 73 caplen - sizeof(struct pfsync_header)); 74 out: 75 if (xflag) { 76 default_print((const u_char *)p, caplen); 77 } 78 putchar('\n'); 79 } 80 81 void 82 pfsync_ip_print(const u_char *bp, u_int len, const u_char *bp2) 83 { 84 struct pfsync_header *hdr = (struct pfsync_header *)bp; 85 struct ip *ip = (struct ip *)bp2; 86 87 if (vflag) 88 printf("%s > %s: ", ipaddr_string(&ip->ip_src), 89 ipaddr_string(&ip->ip_dst)); 90 else 91 printf("%s: ", ipaddr_string(&ip->ip_src)); 92 93 if (len < PFSYNC_HDRLEN) 94 printf("[|pfsync]"); 95 else 96 pfsync_print(hdr, bp + sizeof(struct pfsync_header), 97 len - sizeof(struct pfsync_header)); 98 putchar('\n'); 99 } 100 101 const char *actnames[] = { PFSYNC_ACTIONS }; 102 103 struct pfsync_actions { 104 size_t len; 105 int (*print)(int, const void *); 106 }; 107 108 int pfsync_print_clr(int, const void *); 109 int pfsync_print_state(int, const void *); 110 int pfsync_print_ins_ack(int, const void *); 111 int pfsync_print_upd_c(int, const void *); 112 int pfsync_print_upd_req(int, const void *); 113 int pfsync_print_del_c(int, const void *); 114 int pfsync_print_bus(int, const void *); 115 int pfsync_print_tdb(int, const void *); 116 int pfsync_print_eof(int, const void *); 117 118 struct pfsync_actions actions[] = { 119 { sizeof(struct pfsync_clr), pfsync_print_clr }, 120 { 0, NULL }, 121 { sizeof(struct pfsync_ins_ack), pfsync_print_ins_ack }, 122 { 0, NULL }, 123 { sizeof(struct pfsync_upd_c), pfsync_print_upd_c }, 124 { sizeof(struct pfsync_upd_req), pfsync_print_upd_req }, 125 { sizeof(struct pfsync_state), pfsync_print_state }, 126 { sizeof(struct pfsync_del_c), pfsync_print_del_c }, 127 { 0, NULL }, 128 { 0, NULL }, 129 { sizeof(struct pfsync_bus), pfsync_print_bus }, 130 { 0, NULL }, 131 { 0, pfsync_print_eof }, 132 { sizeof(struct pfsync_state), pfsync_print_state }, 133 { sizeof(struct pfsync_state), pfsync_print_state }, 134 { sizeof(struct pfsync_tdb), pfsync_print_tdb }, 135 }; 136 137 void 138 pfsync_print(struct pfsync_header *hdr, const u_char *bp, int len) 139 { 140 struct pfsync_subheader *subh; 141 int count, plen, alen, flags = 0; 142 int i; 143 144 plen = ntohs(hdr->len); 145 146 printf("PFSYNCv%d len %d", hdr->version, plen); 147 148 if (hdr->version != PFSYNC_VERSION) 149 return; 150 151 plen -= sizeof(*hdr); 152 153 if (vflag) 154 flags |= PF_OPT_VERBOSE; 155 if (vflag > 1) 156 flags |= PF_OPT_VERBOSE2; 157 if (!nflag) 158 flags |= PF_OPT_USEDNS; 159 160 while (plen > 0) { 161 if (len < sizeof(*subh)) 162 break; 163 164 subh = (struct pfsync_subheader *)bp; 165 bp += sizeof(*subh); 166 len -= sizeof(*subh); 167 plen -= sizeof(*subh); 168 169 if (subh->action >= PFSYNC_ACT_MAX) { 170 printf("\n act UNKNOWN id %d", subh->action); 171 return; 172 } 173 174 count = ntohs(subh->count); 175 printf("\n act %s count %d", actnames[subh->action], count); 176 alen = actions[subh->action].len; 177 178 if (actions[subh->action].print == NULL) { 179 printf("\n unimplemented action"); 180 return; 181 } 182 183 for (i = 0; i < count; i++) { 184 if (len < alen) { 185 len = 0; 186 break; 187 } 188 189 if (actions[subh->action].print(flags, bp) != 0) 190 return; 191 192 bp += alen; 193 len -= alen; 194 plen -= alen; 195 } 196 } 197 198 if (plen > 0) { 199 printf("\n ..."); 200 return; 201 } 202 if (plen < 0) { 203 printf("\n invalid header length"); 204 return; 205 } 206 if (len > 0) 207 printf("\n invalid packet length"); 208 } 209 210 int 211 pfsync_print_clr(int flags, const void *bp) 212 { 213 const struct pfsync_clr *clr = bp; 214 char ifname[IFNAMSIZ * 4 + 1]; 215 char *cp = ifname; 216 int i; 217 218 printf("\n\tcreatorid: %08x", htonl(clr->creatorid)); 219 if (clr->ifname[0] != '\0') { 220 /* Treat clr->ifname as untrusted input. */ 221 for (i = 0; i < IFNAMSIZ && clr->ifname[i] != '\0'; i++) 222 cp = vis(cp, clr->ifname[i], VIS_WHITE, 0); 223 printf(" interface: %s", ifname); 224 } 225 226 return (0); 227 } 228 229 int 230 pfsync_print_state(int flags, const void *bp) 231 { 232 struct pfsync_state *st = (struct pfsync_state *)bp; 233 putchar('\n'); 234 print_state(st, flags); 235 return (0); 236 } 237 238 int 239 pfsync_print_ins_ack(int flags, const void *bp) 240 { 241 const struct pfsync_ins_ack *iack = bp; 242 243 printf("\n\tid: %016llx creatorid: %08x", betoh64(iack->id), 244 ntohl(iack->creatorid)); 245 246 return (0); 247 } 248 249 int 250 pfsync_print_upd_c(int flags, const void *bp) 251 { 252 const struct pfsync_upd_c *u = bp; 253 254 printf("\n\tid: %016llx creatorid: %08x", betoh64(u->id), 255 ntohl(u->creatorid)); 256 257 return (0); 258 } 259 260 int 261 pfsync_print_upd_req(int flags, const void *bp) 262 { 263 const struct pfsync_upd_req *ur = bp; 264 265 printf("\n\tid: %016llx creatorid: %08x", betoh64(ur->id), 266 ntohl(ur->creatorid)); 267 268 return (0); 269 } 270 271 int 272 pfsync_print_del_c(int flags, const void *bp) 273 { 274 const struct pfsync_del_c *d = bp; 275 276 printf("\n\tid: %016llx creatorid: %08x", betoh64(d->id), 277 ntohl(d->creatorid)); 278 279 return (0); 280 } 281 282 int 283 pfsync_print_bus(int flags, const void *bp) 284 { 285 const struct pfsync_bus *b = bp; 286 u_int32_t endtime; 287 int min, sec; 288 const char *status; 289 290 endtime = ntohl(b->endtime); 291 sec = endtime % 60; 292 endtime /= 60; 293 min = endtime % 60; 294 endtime /= 60; 295 296 switch (b->status) { 297 case PFSYNC_BUS_START: 298 status = "start"; 299 break; 300 case PFSYNC_BUS_END: 301 status = "end"; 302 break; 303 default: 304 status = "UNKNOWN"; 305 break; 306 } 307 308 printf("\n\tcreatorid: %08x age: %.2u:%.2u:%.2u status: %s", 309 htonl(b->creatorid), endtime, min, sec, status); 310 311 return (0); 312 } 313 314 int 315 pfsync_print_tdb(int flags, const void *bp) 316 { 317 const struct pfsync_tdb *t = bp; 318 319 printf("\n\tspi: 0x%08x rpl: %llu cur_bytes: %llu", 320 ntohl(t->spi), betoh64(t->rpl), betoh64(t->cur_bytes)); 321 322 return (0); 323 } 324 325 int 326 pfsync_print_eof(int flags, const void *bp) 327 { 328 return (1); 329 } 330