1 /* 2 * Copyright (c) 2001-2003 3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4 * All rights reserved. 5 * 6 * Author: Harti Brandt <harti@freebsd.org> 7 * 8 * Redistribution of this software and documentation and use in source and 9 * binary forms, with or without modification, are permitted provided that 10 * the following conditions are met: 11 * 12 * 1. Redistributions of source code or documentation must retain the above 13 * copyright notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS 22 * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 25 * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 28 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 31 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * $Begemot: bsnmp/snmp_mibII/mibII_ip.c,v 1.9 2003/12/03 10:01:19 hbb Exp $ 34 * 35 * ip group scalars. 36 */ 37 #include "mibII.h" 38 #include "mibII_oid.h" 39 #include <netinet/in_systm.h> 40 #include <netinet/ip.h> 41 #include <netinet/ip_var.h> 42 #include <netinet/ip_icmp.h> 43 #include <netinet/icmp_var.h> 44 45 static struct ipstat ipstat; 46 static u_int ip_idrop; 47 static struct icmpstat icmpstat; 48 49 static int ip_forwarding; 50 static int ip_defttl; 51 static u_int32_t ip_tick; 52 53 static u_int32_t ipstat_tick; 54 55 static int 56 fetch_ipstat(void) 57 { 58 size_t len; 59 60 len = sizeof(ipstat); 61 if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, NULL, 0) == -1) { 62 syslog(LOG_ERR, "net.inet.ip.stats: %m"); 63 return (-1); 64 } 65 if (len != sizeof(ipstat)) { 66 syslog(LOG_ERR, "net.inet.ip.stats: wrong size"); 67 return (-1); 68 } 69 len = sizeof(ip_idrop); 70 if (sysctlbyname("net.inet.ip.intr_queue_drops", &ip_idrop, &len, NULL, 0) == -1) 71 syslog(LOG_WARNING, "net.inet.ip.intr_queue_drops: %m"); 72 if (len != sizeof(ip_idrop)) { 73 syslog(LOG_WARNING, "net.inet.ip.intr_queue_drops: wrong size"); 74 ip_idrop = 0; 75 } 76 len = sizeof(icmpstat); 77 if (sysctlbyname("net.inet.icmp.stats", &icmpstat, &len, NULL, 0) == -1) { 78 syslog(LOG_ERR, "net.inet.icmp.stats: %m"); 79 return (-1); 80 } 81 if (len != sizeof(icmpstat)) { 82 syslog(LOG_ERR, "net.inet.icmp.stats: wrong size"); 83 return (-1); 84 } 85 86 ipstat_tick = get_ticks(); 87 return (0); 88 } 89 90 static int 91 fetch_ip(void) 92 { 93 size_t len; 94 95 len = sizeof(ip_forwarding); 96 if (sysctlbyname("net.inet.ip.forwarding", &ip_forwarding, &len, 97 NULL, 0) == -1) { 98 syslog(LOG_ERR, "net.inet.ip.forwarding: %m"); 99 return (-1); 100 } 101 if (len != sizeof(ip_forwarding)) { 102 syslog(LOG_ERR, "net.inet.ip.forwarding: wrong size"); 103 return (-1); 104 } 105 106 len = sizeof(ip_defttl); 107 if (sysctlbyname("net.inet.ip.ttl", &ip_defttl, &len, 108 NULL, 0) == -1) { 109 syslog(LOG_ERR, "net.inet.ip.ttl: %m"); 110 return (-1); 111 } 112 if (len != sizeof(ip_defttl)) { 113 syslog(LOG_ERR, "net.inet.ip.ttl: wrong size"); 114 return (-1); 115 } 116 117 ip_tick = get_ticks(); 118 return (0); 119 } 120 121 static int 122 ip_forward(int forw, int *old) 123 { 124 size_t olen; 125 126 olen = sizeof(*old); 127 if (sysctlbyname("net.inet.ip.forwarding", old, old ? &olen : NULL, 128 &forw, sizeof(forw)) == -1) { 129 syslog(LOG_ERR, "set net.inet.ip.forwarding: %m"); 130 return (-1); 131 } 132 ip_forwarding = forw; 133 return (0); 134 } 135 136 static int 137 ip_setttl(int ttl, int *old) 138 { 139 size_t olen; 140 141 olen = sizeof(*old); 142 if (sysctlbyname("net.inet.ip.ttl", old, old ? &olen : NULL, 143 &ttl, sizeof(ttl)) == -1) { 144 syslog(LOG_ERR, "set net.inet.ip.ttl: %m"); 145 return (-1); 146 } 147 ip_defttl = ttl; 148 return (0); 149 } 150 151 /* 152 * READ/WRITE ip group. 153 */ 154 int 155 op_ip(struct snmp_context *ctx, struct snmp_value *value, 156 u_int sub, u_int idx __unused, enum snmp_op op) 157 { 158 int old; 159 160 switch (op) { 161 162 case SNMP_OP_GETNEXT: 163 abort(); 164 165 case SNMP_OP_GET: 166 break; 167 168 case SNMP_OP_SET: 169 if (ip_tick < this_tick) 170 if (fetch_ip() == -1) 171 return (SNMP_ERR_GENERR); 172 173 switch (value->var.subs[sub - 1]) { 174 175 case LEAF_ipForwarding: 176 ctx->scratch->int1 = ip_forwarding ? 1 : 2; 177 ctx->scratch->int2 = value->v.integer; 178 if (value->v.integer == 1) { 179 if (!ip_forwarding && ip_forward(1, &old)) 180 return (SNMP_ERR_GENERR); 181 ctx->scratch->int1 = old ? 1 : 2; 182 } else if (value->v.integer == 2) { 183 if (ip_forwarding && ip_forward(0, &old)) 184 return (SNMP_ERR_GENERR); 185 ctx->scratch->int1 = old; 186 } else 187 return (SNMP_ERR_WRONG_VALUE); 188 break; 189 190 case LEAF_ipDefaultTTL: 191 ctx->scratch->int1 = ip_defttl; 192 ctx->scratch->int2 = value->v.integer; 193 if (value->v.integer < 1 || value->v.integer > 255) 194 return (SNMP_ERR_WRONG_VALUE); 195 if (ip_defttl != value->v.integer && 196 ip_setttl(value->v.integer, &old)) 197 return (SNMP_ERR_GENERR); 198 ctx->scratch->int1 = old; 199 break; 200 } 201 return (SNMP_ERR_NOERROR); 202 203 case SNMP_OP_ROLLBACK: 204 switch (value->var.subs[sub - 1]) { 205 206 case LEAF_ipForwarding: 207 if (ctx->scratch->int1 == 1) { 208 if (ctx->scratch->int2 == 2) 209 (void)ip_forward(1, NULL); 210 } else { 211 if (ctx->scratch->int2 == 1) 212 (void)ip_forward(0, NULL); 213 } 214 break; 215 216 case LEAF_ipDefaultTTL: 217 if (ctx->scratch->int1 != ctx->scratch->int2) 218 (void)ip_setttl(ctx->scratch->int1, NULL); 219 break; 220 } 221 return (SNMP_ERR_NOERROR); 222 223 case SNMP_OP_COMMIT: 224 return (SNMP_ERR_NOERROR); 225 } 226 227 if (ip_tick < this_tick) 228 if (fetch_ip() == -1) 229 return (SNMP_ERR_GENERR); 230 231 switch (value->var.subs[sub - 1]) { 232 233 case LEAF_ipForwarding: 234 value->v.integer = ip_forwarding ? 1 : 2; 235 break; 236 237 case LEAF_ipDefaultTTL: 238 value->v.integer = ip_defttl; 239 break; 240 } 241 return (SNMP_ERR_NOERROR); 242 } 243 244 /* 245 * READ-ONLY statistics ip group. 246 */ 247 int 248 op_ipstat(struct snmp_context *ctx __unused, struct snmp_value *value, 249 u_int sub, u_int idx __unused, enum snmp_op op) 250 { 251 switch (op) { 252 253 case SNMP_OP_GETNEXT: 254 abort(); 255 256 case SNMP_OP_GET: 257 break; 258 259 case SNMP_OP_SET: 260 return (SNMP_ERR_NOT_WRITEABLE); 261 262 case SNMP_OP_ROLLBACK: 263 case SNMP_OP_COMMIT: 264 abort(); 265 } 266 267 if (ipstat_tick < this_tick) 268 fetch_ipstat(); 269 270 switch (value->var.subs[sub - 1]) { 271 272 case LEAF_ipInReceives: 273 value->v.uint32 = ipstat.ips_total; 274 break; 275 276 case LEAF_ipInHdrErrors: 277 value->v.uint32 = ipstat.ips_badsum + ipstat.ips_tooshort 278 + ipstat.ips_toosmall + ipstat.ips_badhlen 279 + ipstat.ips_badlen + ipstat.ips_badvers + 280 + ipstat.ips_toolong; 281 break; 282 283 case LEAF_ipInAddrErrors: 284 value->v.uint32 = ipstat.ips_cantforward; 285 break; 286 287 case LEAF_ipForwDatagrams: 288 value->v.uint32 = ipstat.ips_forward; 289 break; 290 291 case LEAF_ipInUnknownProtos: 292 value->v.uint32 = ipstat.ips_noproto; 293 break; 294 295 case LEAF_ipInDiscards: 296 value->v.uint32 = ip_idrop; 297 break; 298 299 case LEAF_ipInDelivers: 300 value->v.uint32 = ipstat.ips_delivered; 301 break; 302 303 case LEAF_ipOutRequests: 304 value->v.uint32 = ipstat.ips_localout; 305 break; 306 307 case LEAF_ipOutDiscards: 308 value->v.uint32 = ipstat.ips_odropped; 309 break; 310 311 case LEAF_ipOutNoRoutes: 312 value->v.uint32 = ipstat.ips_noroute; 313 break; 314 315 case LEAF_ipReasmTimeout: 316 value->v.integer = IPFRAGTTL; 317 break; 318 319 case LEAF_ipReasmReqds: 320 value->v.uint32 = ipstat.ips_fragments; 321 break; 322 323 case LEAF_ipReasmOKs: 324 value->v.uint32 = ipstat.ips_reassembled; 325 break; 326 327 case LEAF_ipReasmFails: 328 value->v.uint32 = ipstat.ips_fragdropped 329 + ipstat.ips_fragtimeout; 330 break; 331 332 case LEAF_ipFragOKs: 333 value->v.uint32 = ipstat.ips_fragmented; 334 break; 335 336 case LEAF_ipFragFails: 337 value->v.uint32 = ipstat.ips_cantfrag; 338 break; 339 340 case LEAF_ipFragCreates: 341 value->v.uint32 = ipstat.ips_ofragments; 342 break; 343 } 344 return (SNMP_ERR_NOERROR); 345 } 346 347 /* 348 * READ-ONLY statistics icmp group. 349 */ 350 int 351 op_icmpstat(struct snmp_context *ctx __unused, struct snmp_value *value, 352 u_int sub, u_int idx __unused, enum snmp_op op) 353 { 354 u_int i; 355 356 switch (op) { 357 358 case SNMP_OP_GETNEXT: 359 abort(); 360 361 case SNMP_OP_GET: 362 break; 363 364 case SNMP_OP_SET: 365 return (SNMP_ERR_NOT_WRITEABLE); 366 367 case SNMP_OP_ROLLBACK: 368 case SNMP_OP_COMMIT: 369 abort(); 370 } 371 372 if (ipstat_tick < this_tick) 373 fetch_ipstat(); 374 375 switch (value->var.subs[sub - 1]) { 376 377 case LEAF_icmpInMsgs: 378 value->v.integer = 0; 379 for (i = 0; i <= ICMP_MAXTYPE; i++) 380 value->v.integer += icmpstat.icps_inhist[i]; 381 value->v.integer += icmpstat.icps_tooshort + 382 icmpstat.icps_checksum; 383 /* missing: bad type and packets on faith */ 384 break; 385 386 case LEAF_icmpInErrors: 387 value->v.integer = icmpstat.icps_tooshort + 388 icmpstat.icps_checksum + 389 icmpstat.icps_badlen + 390 icmpstat.icps_badcode + 391 icmpstat.icps_bmcastecho + 392 icmpstat.icps_bmcasttstamp; 393 break; 394 395 case LEAF_icmpInDestUnreachs: 396 value->v.integer = icmpstat.icps_inhist[ICMP_UNREACH]; 397 break; 398 399 case LEAF_icmpInTimeExcds: 400 value->v.integer = icmpstat.icps_inhist[ICMP_TIMXCEED]; 401 break; 402 403 case LEAF_icmpInParmProbs: 404 value->v.integer = icmpstat.icps_inhist[ICMP_PARAMPROB]; 405 break; 406 407 case LEAF_icmpInSrcQuenchs: 408 value->v.integer = icmpstat.icps_inhist[ICMP_SOURCEQUENCH]; 409 break; 410 411 case LEAF_icmpInRedirects: 412 value->v.integer = icmpstat.icps_inhist[ICMP_REDIRECT]; 413 break; 414 415 case LEAF_icmpInEchos: 416 value->v.integer = icmpstat.icps_inhist[ICMP_ECHO]; 417 break; 418 419 case LEAF_icmpInEchoReps: 420 value->v.integer = icmpstat.icps_inhist[ICMP_ECHOREPLY]; 421 break; 422 423 case LEAF_icmpInTimestamps: 424 value->v.integer = icmpstat.icps_inhist[ICMP_TSTAMP]; 425 break; 426 427 case LEAF_icmpInTimestampReps: 428 value->v.integer = icmpstat.icps_inhist[ICMP_TSTAMPREPLY]; 429 break; 430 431 case LEAF_icmpInAddrMasks: 432 value->v.integer = icmpstat.icps_inhist[ICMP_MASKREQ]; 433 break; 434 435 case LEAF_icmpInAddrMaskReps: 436 value->v.integer = icmpstat.icps_inhist[ICMP_MASKREPLY]; 437 break; 438 439 case LEAF_icmpOutMsgs: 440 value->v.integer = 0; 441 for (i = 0; i <= ICMP_MAXTYPE; i++) 442 value->v.integer += icmpstat.icps_outhist[i]; 443 value->v.integer += icmpstat.icps_badaddr + 444 icmpstat.icps_noroute; 445 break; 446 447 case LEAF_icmpOutErrors: 448 value->v.integer = icmpstat.icps_badaddr + 449 icmpstat.icps_noroute; 450 break; 451 452 case LEAF_icmpOutDestUnreachs: 453 value->v.integer = icmpstat.icps_outhist[ICMP_UNREACH]; 454 break; 455 456 case LEAF_icmpOutTimeExcds: 457 value->v.integer = icmpstat.icps_outhist[ICMP_TIMXCEED]; 458 break; 459 460 case LEAF_icmpOutParmProbs: 461 value->v.integer = icmpstat.icps_outhist[ICMP_PARAMPROB]; 462 break; 463 464 case LEAF_icmpOutSrcQuenchs: 465 value->v.integer = icmpstat.icps_outhist[ICMP_SOURCEQUENCH]; 466 break; 467 468 case LEAF_icmpOutRedirects: 469 value->v.integer = icmpstat.icps_outhist[ICMP_REDIRECT]; 470 break; 471 472 case LEAF_icmpOutEchos: 473 value->v.integer = icmpstat.icps_outhist[ICMP_ECHO]; 474 break; 475 476 case LEAF_icmpOutEchoReps: 477 value->v.integer = icmpstat.icps_outhist[ICMP_ECHOREPLY]; 478 break; 479 480 case LEAF_icmpOutTimestamps: 481 value->v.integer = icmpstat.icps_outhist[ICMP_TSTAMP]; 482 break; 483 484 case LEAF_icmpOutTimestampReps: 485 value->v.integer = icmpstat.icps_outhist[ICMP_TSTAMPREPLY]; 486 break; 487 488 case LEAF_icmpOutAddrMasks: 489 value->v.integer = icmpstat.icps_outhist[ICMP_MASKREQ]; 490 break; 491 492 case LEAF_icmpOutAddrMaskReps: 493 value->v.integer = icmpstat.icps_outhist[ICMP_MASKREPLY]; 494 break; 495 } 496 return (SNMP_ERR_NOERROR); 497 } 498