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