1 /* $OpenBSD: print-rip.c,v 1.12 2009/10/27 23:59:55 deraadt 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/param.h> 25 #include <sys/time.h> 26 #include <sys/socket.h> 27 28 #include <netinet/in.h> 29 #include <netinet/in_systm.h> 30 #include <netinet/ip.h> 31 #include <netinet/ip_var.h> 32 #include <netinet/udp.h> 33 #include <netinet/udp_var.h> 34 35 #include <stdio.h> 36 #include <string.h> 37 #include <ctype.h> 38 39 #include "interface.h" 40 #include "addrtoname.h" 41 #include "extract.h" /* must come after interface.h */ 42 43 struct rip { 44 u_char rip_cmd; /* request/response */ 45 u_char rip_vers; /* protocol version # */ 46 u_short rip_zero2; /* unused */ 47 }; 48 #define RIPCMD_REQUEST 1 /* want info */ 49 #define RIPCMD_RESPONSE 2 /* responding to request */ 50 #define RIPCMD_TRACEON 3 /* turn tracing on */ 51 #define RIPCMD_TRACEOFF 4 /* turn it off */ 52 #define RIPCMD_POLL 5 /* want info from everybody */ 53 #define RIPCMD_POLLENTRY 6 /* poll for entry */ 54 55 #define RIP_AUTHLEN 16 56 57 struct rip_netinfo { 58 u_short rip_family; 59 u_short rip_tag; 60 u_int32_t rip_dest; 61 u_int32_t rip_dest_mask; 62 u_int32_t rip_router; 63 u_int32_t rip_metric; /* cost of route */ 64 }; 65 66 static void 67 rip_printblk(const u_char *cp, const u_char *ep) 68 { 69 for (; cp < ep; cp += 2) 70 printf(" %04x", EXTRACT_16BITS(cp)); 71 return; 72 } 73 74 static void 75 rip_entry_print_v1(register int vers, register const struct rip_netinfo *ni) 76 { 77 register u_short family; 78 79 /* RFC 1058 */ 80 family = EXTRACT_16BITS(&ni->rip_family); 81 if (family != AF_INET) { 82 printf(" [family %d:", family); 83 rip_printblk((u_char *)&ni->rip_tag, 84 (u_char *)&ni->rip_metric + 85 sizeof(ni->rip_metric)); 86 printf("]"); 87 return; 88 } 89 if (ni->rip_tag || ni->rip_dest_mask || ni->rip_router) { 90 /* MBZ fields not zero */ 91 printf(" ["); 92 rip_printblk((u_char *)&ni->rip_family, 93 (u_char *)&ni->rip_metric + 94 sizeof(ni->rip_metric)); 95 printf("]"); 96 return; 97 } 98 printf(" {%s}(%d)", ipaddr_string(&ni->rip_dest), 99 EXTRACT_32BITS(&ni->rip_metric)); 100 } 101 102 static void 103 rip_entry_print_v2(register int vers, register const struct rip_netinfo *ni) 104 { 105 register u_char *p; 106 register u_short family; 107 char buf[RIP_AUTHLEN]; 108 109 /* RFC 1723 */ 110 family = EXTRACT_16BITS(&ni->rip_family); 111 if (family == 0xFFFF) { 112 if (EXTRACT_16BITS(&ni->rip_tag) == 2) { 113 memcpy(buf, &ni->rip_dest, sizeof(buf)); 114 buf[sizeof(buf)-1] = '\0'; 115 for (p = buf; *p; p++) { 116 if (!isprint(*p)) 117 break; 118 } 119 if (!*p) { 120 printf(" [password %s]", buf); 121 } else { 122 printf(" [password: "); 123 rip_printblk((u_char *)&ni->rip_dest, 124 (u_char *)&ni->rip_metric + 125 sizeof(ni->rip_metric)); 126 printf("]"); 127 } 128 } else { 129 printf(" [auth %d:", 130 EXTRACT_16BITS(&ni->rip_tag)); 131 rip_printblk((u_char *)&ni->rip_dest, 132 (u_char *)&ni->rip_metric + 133 sizeof(ni->rip_metric)); 134 printf("]"); 135 } 136 } else if (family != AF_INET) { 137 printf(" [family %d:", family); 138 rip_printblk((u_char *)&ni->rip_tag, 139 (u_char *)&ni->rip_metric + 140 sizeof(ni->rip_metric)); 141 printf("]"); 142 return; 143 } else { /* AF_INET */ 144 printf(" {%s", ipaddr_string(&ni->rip_dest)); 145 if (ni->rip_dest_mask) 146 printf("/%s", ipaddr_string(&ni->rip_dest_mask)); 147 if (ni->rip_router) 148 printf("->%s", ipaddr_string(&ni->rip_router)); 149 if (ni->rip_tag) 150 printf(" tag %04x", EXTRACT_16BITS(&ni->rip_tag)); 151 printf("}(%d)", EXTRACT_32BITS(&ni->rip_metric)); 152 } 153 } 154 155 void 156 rip_print(const u_char *dat, u_int length) 157 { 158 register const struct rip *rp; 159 register const struct rip_netinfo *ni; 160 register int i, j, trunc; 161 162 i = min(length, snapend - dat) - sizeof(*rp); 163 if (i < 0) { 164 printf(" [|rip]"); 165 return; 166 } 167 168 rp = (struct rip *)dat; 169 switch (rp->rip_vers) { 170 case 0: 171 /* RFC 1058 */ 172 printf(" RIPv0: "); 173 rip_printblk((u_char *)(rp + 1), snapend); 174 break; 175 default: 176 switch (rp->rip_cmd) { 177 case RIPCMD_REQUEST: 178 printf(" RIPv%d-req %d", rp->rip_vers, length); 179 break; 180 case RIPCMD_RESPONSE: 181 j = length / sizeof(*ni); 182 if (j * sizeof(*ni) != length - 4) 183 printf(" RIPv%d-resp [items %d] [%d]:", 184 rp->rip_vers, j, length); 185 else 186 printf(" RIPv%d-resp [items %d]:", 187 rp->rip_vers, j); 188 trunc = (i / sizeof(*ni)) != j; 189 ni = (struct rip_netinfo *)(rp + 1); 190 for (; (i -= sizeof(*ni)) >= 0; ++ni) { 191 if (rp->rip_vers == 1) 192 rip_entry_print_v1(rp->rip_vers, ni); 193 else 194 rip_entry_print_v2(rp->rip_vers, ni); 195 } 196 if (trunc) 197 printf("[|rip]"); 198 break; 199 case RIPCMD_TRACEON: 200 printf(" RIPv%d-traceon %d: \"", rp->rip_vers, length); 201 (void)fn_print((const u_char *)(rp + 1), snapend); 202 fputs("\"\n", stdout); 203 break; 204 case RIPCMD_TRACEOFF: 205 printf(" RIPv%d-traceoff %d", rp->rip_vers, length); 206 break; 207 case RIPCMD_POLL: 208 printf(" RIPv%d-poll %d", rp->rip_vers, length); 209 break; 210 case RIPCMD_POLLENTRY: 211 printf(" RIPv%d-pollentry %d", rp->rip_vers, length); 212 break; 213 default: 214 printf(" RIPv%d-#%d %d", rp->rip_vers, rp->rip_cmd, 215 length); 216 break; 217 } 218 } 219 } 220