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
rip_printblk(const u_char * cp,const u_char * ep)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
rip_entry_print_v1(int vers,const struct rip_netinfo * ni)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
rip_entry_print_v2(int vers,const struct rip_netinfo * ni)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
rip_print(const u_char * dat,u_int length)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