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