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