1 /* $OpenBSD: print-rip.c,v 1.18 2020/01/24 22:46:37 procter Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1996 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that: (1) source code distributions 9 * retain the above copyright notice and this paragraph in its entirety, (2) 10 * distributions including binary code include the above copyright notice and 11 * this paragraph in its entirety in the documentation or other materials 12 * provided with the distribution, and (3) all advertising materials mentioning 13 * features or use of this software display the following acknowledgement: 14 * ``This product includes software developed by the University of California, 15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 * the University nor the names of its contributors may be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 */ 23 24 #include <sys/time.h> 25 #include <sys/socket.h> 26 27 #include <netinet/in.h> 28 #include <netinet/ip.h> 29 #include <netinet/ip_var.h> 30 #include <netinet/udp.h> 31 #include <netinet/udp_var.h> 32 33 #include <stdio.h> 34 #include <string.h> 35 #include <ctype.h> 36 37 #include "interface.h" 38 #include "addrtoname.h" 39 #include "extract.h" /* must come after interface.h */ 40 41 struct rip { 42 u_char rip_cmd; /* request/response */ 43 u_char rip_vers; /* protocol version # */ 44 u_short rip_zero2; /* unused */ 45 }; 46 #define RIPCMD_REQUEST 1 /* want info */ 47 #define RIPCMD_RESPONSE 2 /* responding to request */ 48 #define RIPCMD_TRACEON 3 /* turn tracing on */ 49 #define RIPCMD_TRACEOFF 4 /* turn it off */ 50 #define RIPCMD_POLL 5 /* want info from everybody */ 51 #define RIPCMD_POLLENTRY 6 /* poll for entry */ 52 53 #define RIP_AUTHLEN 16 54 55 struct rip_netinfo { 56 u_short rip_family; 57 u_short rip_tag; 58 u_int32_t rip_dest; 59 u_int32_t rip_dest_mask; 60 u_int32_t rip_router; 61 u_int32_t rip_metric; /* cost of route */ 62 }; 63 64 static void 65 rip_printblk(const u_char *cp, const u_char *ep) 66 { 67 for (; cp < ep; cp += 2) 68 printf(" %04x", EXTRACT_16BITS(cp)); 69 return; 70 } 71 72 static void 73 rip_entry_print_v1(int vers, const struct rip_netinfo *ni) 74 { 75 u_short family; 76 77 /* RFC 1058 */ 78 family = EXTRACT_16BITS(&ni->rip_family); 79 if (family != AF_INET) { 80 printf(" [family %d:", family); 81 rip_printblk((u_char *)&ni->rip_tag, 82 (u_char *)&ni->rip_metric + 83 sizeof(ni->rip_metric)); 84 printf("]"); 85 return; 86 } 87 if (ni->rip_tag || ni->rip_dest_mask || ni->rip_router) { 88 /* MBZ fields not zero */ 89 printf(" ["); 90 rip_printblk((u_char *)&ni->rip_family, 91 (u_char *)&ni->rip_metric + 92 sizeof(ni->rip_metric)); 93 printf("]"); 94 return; 95 } 96 printf(" {%s}(%d)", ipaddr_string(&ni->rip_dest), 97 EXTRACT_32BITS(&ni->rip_metric)); 98 } 99 100 static void 101 rip_entry_print_v2(int vers, const struct rip_netinfo *ni) 102 { 103 u_char *p; 104 u_short family; 105 char buf[RIP_AUTHLEN]; 106 107 /* RFC 1723 */ 108 family = EXTRACT_16BITS(&ni->rip_family); 109 if (family == 0xFFFF) { 110 if (EXTRACT_16BITS(&ni->rip_tag) == 2) { 111 memcpy(buf, &ni->rip_dest, sizeof(buf)); 112 buf[sizeof(buf)-1] = '\0'; 113 for (p = buf; *p; p++) { 114 if (!isprint(*p)) 115 break; 116 } 117 if (!*p) { 118 printf(" [password %s]", buf); 119 } else { 120 printf(" [password: "); 121 rip_printblk((u_char *)&ni->rip_dest, 122 (u_char *)&ni->rip_metric + 123 sizeof(ni->rip_metric)); 124 printf("]"); 125 } 126 } else { 127 printf(" [auth %d:", 128 EXTRACT_16BITS(&ni->rip_tag)); 129 rip_printblk((u_char *)&ni->rip_dest, 130 (u_char *)&ni->rip_metric + 131 sizeof(ni->rip_metric)); 132 printf("]"); 133 } 134 } else if (family != AF_INET) { 135 printf(" [family %d:", family); 136 rip_printblk((u_char *)&ni->rip_tag, 137 (u_char *)&ni->rip_metric + 138 sizeof(ni->rip_metric)); 139 printf("]"); 140 return; 141 } else { /* AF_INET */ 142 printf(" {%s", ipaddr_string(&ni->rip_dest)); 143 if (ni->rip_dest_mask) 144 printf("/%s", ipaddr_string(&ni->rip_dest_mask)); 145 if (ni->rip_router) 146 printf("->%s", ipaddr_string(&ni->rip_router)); 147 if (ni->rip_tag) 148 printf(" tag %04x", EXTRACT_16BITS(&ni->rip_tag)); 149 printf("}(%d)", EXTRACT_32BITS(&ni->rip_metric)); 150 } 151 } 152 153 void 154 rip_print(const u_char *dat, u_int length) 155 { 156 const struct rip *rp; 157 const struct rip_netinfo *ni; 158 int i, j, trunc; 159 160 i = min(length, snapend - dat) - sizeof(*rp); 161 if (i < 0) { 162 printf("[|rip]"); 163 return; 164 } 165 166 rp = (struct rip *)dat; 167 switch (rp->rip_vers) { 168 case 0: 169 /* RFC 1058 */ 170 printf("RIPv0: "); 171 rip_printblk((u_char *)(rp + 1), snapend); 172 break; 173 default: 174 switch (rp->rip_cmd) { 175 case RIPCMD_REQUEST: 176 printf("RIPv%d-req %d", rp->rip_vers, length); 177 break; 178 case RIPCMD_RESPONSE: 179 j = length / sizeof(*ni); 180 if (j * sizeof(*ni) != length - 4) 181 printf("RIPv%d-resp [items %d] [%d]:", 182 rp->rip_vers, j, length); 183 else 184 printf("RIPv%d-resp [items %d]:", 185 rp->rip_vers, j); 186 trunc = (i / sizeof(*ni)) != j; 187 ni = (struct rip_netinfo *)(rp + 1); 188 for (; (i -= sizeof(*ni)) >= 0; ++ni) { 189 if (rp->rip_vers == 1) 190 rip_entry_print_v1(rp->rip_vers, ni); 191 else 192 rip_entry_print_v2(rp->rip_vers, ni); 193 } 194 if (trunc) 195 printf("[|rip]"); 196 break; 197 case RIPCMD_TRACEON: 198 printf("RIPv%d-traceon %d: \"", rp->rip_vers, length); 199 (void)fn_print((const u_char *)(rp + 1), snapend); 200 printf("\""); 201 break; 202 case RIPCMD_TRACEOFF: 203 printf("RIPv%d-traceoff %d", rp->rip_vers, length); 204 break; 205 case RIPCMD_POLL: 206 printf("RIPv%d-poll %d", rp->rip_vers, length); 207 break; 208 case RIPCMD_POLLENTRY: 209 printf("RIPv%d-pollentry %d", rp->rip_vers, length); 210 break; 211 default: 212 printf("RIPv%d-#%d %d", rp->rip_vers, rp->rip_cmd, 213 length); 214 break; 215 } 216 } 217 } 218